
lib file = <file.ssz>;
lib s = <string.ssz>;
lib sdl = <alpha/sdlplugin.ssz>;
lib consts = <consts.ssz>;
lib m = <math.ssz>;
lib sff = "sff.ssz";
lib cmd = "command.ssz";
lib stage = "stage.ssz";
lib com = "common.ssz";
lib cfg = "config.ssz";
lib snd = "sound.ssz";
lib fgt = "fight.ssz";
lib act = "action.ssz";
lib mes = <alpha/mesdialog.ssz>;
lib fnt = "font.ssz";
lib al = <alert.ssz>;
lib tbl = <table.ssz>;
lib se = <alpha/sdlevent.ssz>;


int changeStateNest = 0;
int waitdown = 0, shuttertime = 0;
bool winskipped = false;
void none;

|fgt.KOTy ko = fgt.KOTy::NotYet;
^|fgt.WinTy winty.new(2);
winty[0] = fgt.WinTy::N;
winty[1] = fgt.WinTy::N;
public ^index wakewakaLength;

public ^&.stage.Stage stg;

%&act.DrawnClsn drawc1, drawc2, drawc2sp, drawc2mtk, drawwh;
void resetDrawnClsnList()
{
  .drawc1.new(0);
  .drawc2.new(0);
  .drawc2sp.new(0);
  .drawc2mtk.new(0);
  .drawwh.new(0);
}
void drawClsn()
{
  ^ubyte pxl;
  pxl.new(1);
  pxl<> = 0x0;
  &.sff.Sprite spr.rct.set(0, 0, 1, 1);
  spr.colorPallet.new(256);
  spr.colorPallet<> = 0xff0000;
  spr.setPxl(pxl);
  .drawc1:<-[void(i=){i.draw(spr=, (int)0x3feff);}];
  spr.colorPallet<> = 0x0000ff;
  .drawc2:<-[void(i=){i.draw(spr=, (int)0x3feff);}];
  spr.colorPallet<> = 0x00ff00;
  .drawc2sp:<-[void(i=){i.draw(spr=, (int)0x3feff);}];
  spr.colorPallet<> = 0x002000;
  .drawc2mtk:<-[void(i=){i.draw(spr=, (int)0x3feff);}];
  spr.colorPallet<> = 0x404040;
  .drawwh:<-[void(i=){i.draw(spr=, (int)0x3feff);}];
}

&AnimSprite
{
  public ^&.act.Action anim;
  public int priority = 0;
  public float x = 0.0, y = 0.0;
  public float xscl = 1.0, yscl = 1.0, angle = 0.0, axscl = 1.0, ayscl = 1.0;
  public bool padding, oVer = false, screen = false, bright = false;
  public int salpha = -1, dalpha = 0;
  public ^&.com.PalFX fx;
}

%^&AnimSprite anims, topanims;

&ShadowSprite
{
  public ^&.AnimSprite as;
  public int color, alpha;
  public float offsety = 0.0, fadeoffset = 0.0;
}

%^&ShadowSprite shadows;

public void addAnimList(
  %^&.AnimSprite al=, ^&.act.Action a, int p, float x, float y, bool scr,
  float xs, float ys, float an, bool oVer, float ax, float ay, int sa, int da,
  bool b, ^&.com.PalFX fx, int sc, int salp, float so, float fo)
{
  ^&.AnimSprite newSprite()
  {
    ^&.AnimSprite as.new(1);
    as.new(1);
    as~anim = `a;
    as~priority = `p;
    as~x = `x;
    as~y = `y;
    as~screen = `scr;
    as~xscl = `xs;
    as~yscl = `ys;
    as~angle = `an;
    as~oVer = `oVer;
    as~bright = `b;
    as~axscl = `ax;
    as~ayscl = `ay;
    as~salpha = `sa;
    as~dalpha = `da;
    as~fx = `fx;
    if(`sc != 0) .addShadowList(as, `sc, `so, `salp, `fo);
    ret as;
  }
  if(.se.fskip || #a == 0 || #a~ani.spr == 0) ret;
  loop{
    index i = 0, start = 0, length = #al;
    while;
  do:
    i = start + (length >> 1);
    branch{
    cond p <= al[i]~priority:
      length = i - start;
    cond i == start:
      i++;
      length = 0;
    else:
      length -= i - start;
      start = i;
    }
  while length > 0:
    {
      *al.self tmp .= al[0 .. i] .= newSprite() .= al[i .. -1];
      al = tmp;
    }
  }
}

public void drawAnimList(%^&.AnimSprite al=, float x, float y, float scl)
{
  loop{index i = 0; while; do:
    al[i]~[void(as=){
      as.anim~ani.salpha = as.salpha;
      as.anim~ani.dalpha = as.dalpha;
      branch{
        int ob = .com.brightness;
        if(as.bright) .com.brightness = 256;
        float cs = as.screen ? 1.0 : scl, px, py;
      cond as.angle != 0.0:
        branch{
        cond as.screen:
          px = as.x;
          py = as.y + (float)(.com.GameHeight - 240);
        else:
          px = .com.cam.xOffset - (x - as.x) * cs;
          py =
            .com.cam.groundLevel() + .com.cam.yOffset
            - .stage.envShake.getOffset() - (y - as.y) * cs;
        }
        as.anim~ani.angleDraw(
          px, py, cs * as.xscl * as.axscl, cs * as.yscl * as.ayscl,
          as.angle*(.m.PI/180.0), as.fx, as.oVer);
      else:
        branch{
        cond as.screen:
          px = as.x;
          py = as.y + (float)(.com.GameHeight - 240);
        else:
          px = .com.cam.xOffset / cs - (x - as.x);
          py =
            (
              .com.cam.groundLevel() + .com.cam.yOffset
              - .stage.envShake.getOffset())
            / cs - (y - as.y);
        }
        as.anim~ani.draw(
          .com.scrrect=, px, py, cs, cs, as.xscl, as.xscl,
          as.yscl, 0.0, (float).com.GameWidth/2.0, as.fx, as.oVer);
      break:
        .com.brightness = ob;
      }
    }];
    i++;
  while i < #al:}
}

public void addShadowList(
  ^&.AnimSprite as, int sc, float so, int alpha, float fo)
{
  ^&.ShadowSprite newSprite()
  {
    ^&.ShadowSprite ss.new(1);
    ss~as = `as;
    ss~color = `sc;
    ss~alpha = .m.max!int?(0, .m.min!int?(256, `alpha));
    ss~offsety = `so * (`as~oVer ? 1.5 : 1.0);
    ss~fadeoffset = `fo;
    ret ss;
  }
  int p = as~priority;
  loop{
    index i = 0, start = 0, length = #.shadows;
    while;
  do:
    i = start + (length >> 1);
    branch{
    cond p <= .shadows[i]~as~priority:
      length = i - start;
    cond i == start:
      i++;
      length = 0;
    else:
      length -= i - start;
      start = i;
    }
  while length > 0:
    {
      *.shadows.self tmp .=
        .shadows[0 .. i] .= newSprite() .= .shadows[i .. -1];
      .shadows = tmp;
    }
  }
}

public void drawShadowList(float x, float y, float scl)
{
  /* loop{index i = 0; while; do:
    .shadows[i]~[void(ss=){
      int intensity = .stg~sdw.intensity;
      int color = ss.color;
      branch{
        int alpha = ss.alpha;
        branch{
          float y = ss.as~y - ss.fadeoffset;
        cond .stg~sdw.fadebgn <= .stg~sdw.fadeend:
        cond y <= (float).stg~sdw.fadeend * .stg~localscl:
          ret;
        cond y < (float).stg~sdw.fadebgn * .stg~localscl:
          alpha =
            (int)(
              (float)alpha * ((float).stg~sdw.fadeend * .stg~localscl - y)
              / (
                ((float).stg~sdw.fadeend - (float).stg~sdw.fadebgn)
                * .stg~localscl));
        }
      cond color < 0:
        color = (int).stg~sdw.color;
        if(alpha >= 255) break;
        intensity = intensity * alpha >> 8;
      else:
        intensity = 0;
      comm:
        color =
          (color & 255)*alpha>>8 & 255 | (color & 255<<8)*alpha>>8 & 255<<8
          | (color & 255<<16)*alpha>>8 & 255<<16;
      }
      float syscl = .stg~sdw.yscale;
      ss.as~anim~ani.shadowDraw(
        .com.cam.xOffset - (x - ss.as~x) * scl,
        .com.cam.groundLevel() + .com.cam.yOffset - .stage.envShake.getOffset()
        - (y + ss.as~y * syscl - ss.offsety) * scl,
        scl * ss.as~xscl * ss.as~axscl, scl * -ss.as~yscl * ss.as~ayscl,
        syscl, -ss.as~angle*(.m.PI/180.0), .stage.bgPalFX, ss.as~oVer,
        (uint)color, intensity);
    }];
  continue:
    i++;
  while i < #.shadows:}
  */
}

public void drawReflection(float x, float y, float scl)
{
  loop{index i = 0; while; do:
    .shadows[i]~[void(ss=){
      if(ss.as~salpha < 0){
        ss.as~salpha =
          (int)ss.as~anim~ani.frames[ss.as~anim~ani.drawidx].salpha;
        ss.as~dalpha =
          (int)ss.as~anim~ani.frames[ss.as~anim~ani.drawidx].dalpha;
        if(ss.as~salpha == 255 && ss.as~dalpha == 1){
          ss.as~dalpha = 255;
        }
      }
      int refl = .stg~reflection*ss.alpha >> 8;
      ss.as~anim~ani.salpha = (int)((float)(ss.as~salpha * refl) / 255.0);
      ss.as~anim~ani.dalpha =
        .m.min!int?(
          255, (ss.as~dalpha >= 0 ? ss.as~dalpha : 128) + (255-refl));
      if(ss.as~anim~ani.salpha == 1 && ss.as~anim~ani.dalpha == 255){
        ss.as~anim~ani.salpha = 0;
      }
      branch{
      cond ss.as~angle != 0.0:
        ss.as~anim~ani.angleDraw(
          .com.cam.xOffset - (x - ss.as~x) * scl,
          .com.cam.groundLevel() + .com.cam.yOffset
          - .stage.envShake.getOffset() - (y + ss.as~y - ss.offsety) * scl,
          scl * ss.as~xscl * ss.as~axscl, scl * -ss.as~yscl * ss.as~ayscl,
          -ss.as~angle*(.m.PI/180.0), ss.as~fx, ss.as~oVer);
      else:
        ss.as~anim~ani.draw(
          .com.scrrect=, .com.cam.xOffset / scl - (x - ss.as~x),
          (
            .com.cam.groundLevel() + .com.cam.yOffset
            - .stage.envShake.getOffset())
          / scl - (y + ss.as~y - ss.offsety),
          scl, scl, ss.as~xscl, ss.as~xscl, -ss.as~yscl, 0.0,
          (float).com.GameWidth/2.0, ss.as~fx, ss.as~oVer);
      }
    }];
  continue:
    i++;
  while i < #.shadows:}
}


&AfterImage
{
  &ImgInfo
  {
    public ^&.act.Action anim;
    public float x = 0.0, y = 0.0, xscl = 1.0, yscl = 1.0;
    public float angle = 0.0, axscl = 1.0, ayscl = 1.0;
    public bool oVer = false;
    new()
    {
      `anim.new(1);
    }
  }
  public int time;
  public int length;
  public int postbrightr;
  public int postbrightg;
  public int postbrightb;
  public int addr;
  public int addg;
  public int addb;
  public float mulr;
  public float mulg;
  public float mulb;
  public int timegap;
  public int framegap;
  public int alphas;
  public int alphad;
  public ^&.com.PalFX palfx;
  public ^&ImgInfo imgs;
  public int imgidx;
  public int restgap;
  public int reccount;
  new()
  {
    `palfx.new(.cfg.AfterImageMax);
    loop{index i = 0; while; do:
      `palfx[i].enable = true;
      `palfx[i].negType = 1;
      i++;
    while i < #`palfx:}
    `clear();
    `timegap = 0;
    `imgs.new(64);
  }
  public void clear()
  {
    `time = 0;
    `length = 20;
    if(#`palfx > 0){
      `palfx~ecolor = 1.0;
      `palfx~einvertall = 0;
      `palfx~eaddr = 30;
      `palfx~eaddg = 30;
      `palfx~eaddb = 30;
      `palfx~emulr = 120;
      `palfx~emulg = 120;
      `palfx~emulb = 220;
    }
    `postbrightr = 0;
    `postbrightg = 0;
    `postbrightb = 0;
    `addr = 10;
    `addg = 10;
    `addb = 25;
    `mulr = 0.65;
    `mulg = 0.65;
    `mulb = 0.75;
    `timegap = 1;
    `framegap = 6;
    `alphas = -1;
    `alphad = 0;
    `imgidx = 0;
    `restgap = 0;
    `reccount = 0;
  }
  public void setPalcolor(int palcol)
  {
    if(#`palfx > 0){
      `palfx~ecolor = (float)palcol / 256.0;
      .m.limRange!float?(`palfx~ecolor=, 0.0, 1.0);
    }
  }
  public void setPalinvertall(bool palinv)
  {
    if(#`palfx > 0) `palfx~einvertall = (int)palinv;
  }
  public void setPalbrightR(int palbrr)
  {
    if(#`palfx > 0) `palfx~eaddr = palbrr;
  }
  public void setPalbrightG(int palbrg)
  {
    if(#`palfx > 0) `palfx~eaddg = palbrg;
  }
  public void setPalbrightB(int palbrb)
  {
    if(#`palfx > 0) `palfx~eaddb = palbrb;
  }
  public void setPalcontrastR(int palcor)
  {
    if(#`palfx > 0) `palfx~emulr = palcor;
  }
  public void setPalcontrastG(int palcog)
  {
    if(#`palfx > 0) `palfx~emulg = palcog;
  }
  public void setPalcontrastB(int palcob)
  {
    if(#`palfx > 0) `palfx~emulb = palcob;
  }
  public void setupPalfx()
  {
    loop{
      index i = 1;
      int pbr = `postbrightr, pbg = `postbrightg, pbb = `postbrightb;
      while;
    do:
      `palfx[i].ecolor = `palfx[i-1].ecolor;
      `palfx[i].einvertall = `palfx[i-1].einvertall;
      `palfx[i].eaddr = `palfx[i-1].eaddr + `addr + pbr;
      `palfx[i].eaddg = `palfx[i-1].eaddg + `addg + pbg;
      `palfx[i].eaddb = `palfx[i-1].eaddb + `addb + pbb;
      pbr = pbg = pbb = 0;
      `palfx[i].emulr = (int)((float)`palfx[i-1].emulr * `mulr);
      `palfx[i].emulg = (int)((float)`palfx[i-1].emulg * `mulg);
      `palfx[i].emulb = (int)((float)`palfx[i-1].emulb * `mulb);
      i++;
    while i < #`palfx:}
  }
  public void recAfterImg(
    &.act.Action a=, float x, float y, float xs, float ys,
    float an, bool oVer, float ax, float ay, ^&.com.PalFX cfx)
  {
    if(`time == 0){
      `reccount = `timegap = 0;
      ret;
    }
    if(`time > 0) `time--;
    if(`restgap <= 0){
      `imgs[`imgidx].[void(i=){
        i.anim~copy(a=);
        if(#a.ani.spr > 0){
          i.anim~ani.spr.new(1);
          i.anim~ani.spr~copy(a.ani.spr<>=);
          a.ani.sff~palList.swapPalMap(cfx~remap=);
          i.anim~ani.spr~colorPallet = a.ani.spr~getPal(a.ani.sff~palList=);
          a.ani.sff~palList.swapPalMap(cfx~remap=);
        }
        i.x = x;
        i.y = y;
        i.xscl = xs;
        i.yscl = ys;
        i.angle = an;
        i.oVer = oVer;
        i.axscl = ax;
        i.ayscl = ay;
      }];
      `imgidx = `imgidx+1 & 63;
      if(`reccount < #`imgs) `reccount++;
      `restgap = `timegap;
    }
    `restgap--;
  }
  public void recAndAddAL(
    &.act.Action a=, int p, float x, float y, float xs, float ys, float an,
    bool oVer, float ax, float ay, bool rec, bool br, ^&.com.PalFX cfx)
  {
    if(
      `time == 0 || !.m.inRange!int?(1, 32767, `timegap)
      || !.m.inRange!int?(1, 32767, `framegap))
    {
      `time = 0;
      `reccount = `timegap = 0;
      ret;
    }
    loop{
      index i = `framegap, pfxi;
      index end = (.m.min!int?(`reccount, `length)/`framegap) * `framegap;
      .m.limMax!index?(end=, .cfg.AfterImageMax*`framegap);
      while;
    do:
      pfxi = i/`framegap - 1;
      .addAnimList(
        .anims=, `imgs[`imgidx-i&63].anim, p-2,
        `imgs[`imgidx-i&63].x, `imgs[`imgidx-i&63].y, false,
        `imgs[`imgidx-i&63].xscl, `imgs[`imgidx-i&63].yscl,
        `imgs[`imgidx-i&63].angle, `imgs[`imgidx-i&63].oVer,
        `imgs[`imgidx-i&63].axscl, `imgs[`imgidx-i&63].ayscl,
        `alphas, `alphad, br, `palfx[pfxi .. pfxi + 1],
        0, 0, 0.0, 0.0);
      i += `framegap;
    while i <= end:}
    if(rec) `recAfterImg(a=, x, y, xs, ys, an, oVer, ax, ay, cfx);
  }
}


void pLrSet(float dl=, float dr=, float sl, float sr)
{
  dl = sl;
  dr = sr + 1.0;
}
void mLrSet(float dl=, float dr=, float sl, float sr)
{
  dl = -sr;
  dr = -sl + 1.0;
}

&ClsnHantei
{
  float xscl1, yscl1;
  float xofs1, yofs1;
  func$void(float=, float=, float, float) lrset1 = .pLrSet;
  float xscl2, yscl2;
  float xofs2, yofs2;
  func$void(float=, float=, float, float) lrset2 = .pLrSet;
  public void set(
    float xs1, float ys1, float xo1, float yo1, `lrset1.self lr1, 
    float xs2, float ys2, float xo2, float yo2, `lrset2.self lr2)
  {
    `xscl1 = xs1;
    `yscl1 = ys1;
    `xofs1 = xo1;
    `yofs1 = yo1;
    `lrset1 = lr1;
    `xscl2 = xs2;
    `yscl2 = ys2;
    `xofs2 = xo2;
    `yofs2 = yo2;
    `lrset2 = lr2;
  }
  /bool hantei(&.act.Rect c1, &.act.Rect c2)
  {
    float l1, r1, l2, r2;
    `lrset1(:l1=, r1=, (float)c1.l, (float)c1.r:);
    `lrset2(:l2=, r2=, (float)c2.l, (float)c2.r:);
    ret
      l1*`xscl1+`xofs1 < r2*`xscl2+`xofs2
      && l2*`xscl2+`xofs2 < r1*`xscl1+`xofs1
      && (float)c1.t*`yscl1+`yofs1 < ((float)c2.b+1.0)*`yscl2+`yofs2
      && (float)c2.t*`yscl2+`yofs2 < ((float)c1.b+1.0)*`yscl1+`yofs1;
  }
}


|VarTy
{
  Int, Float, SFalse
}
public &Var
{
  public |.VarTy typ = .VarTy::Int;
  public int i = 0;
  public float f = 0.0;
  public void setI(int i)
  {
    `typ = .VarTy::Int;
    `i = i;
  }
  public void setF(float f)
  {
    if(.m.isnan(f)){
      `setSF();
      ret;
    }
    `typ = .VarTy::Float;
    `f = f;
  }
  public void setB(bool b)
  {
    `typ = .VarTy::Int;
    `i = (int)b;
  }
  public void setSF()
  {
    `typ = .VarTy::SFalse;
  }
  /bool isT()
  {
    if(`isSF()) ret false;
    ret `typ == .VarTy::Int ? `i != 0 : `f != 0.0;
  }
  /bool isSF()
  {
    ret `typ == .VarTy::SFalse;
  }
  /int toI()
  {
    if(`isSF()) ret 0;
    ret `typ == .VarTy::Int ? `i : (int)`f;
  }
  /double toF()
  {
    if(`isSF()) ret 0.0;
    ret `typ == .VarTy::Int ? (double)`i : `f;
  }
}
public &Var v;//work
public ^&Char c;//work
type _t = $void(&Char=);
void rd(~$void(&.Char=) f)
{
  if(#.c == 0){
    .v.setSF();
    ret;
  }
  f(:.c<>=:);
}

public void appendClipboardText(int p, ^/char text)
{
  .com.clipboardText[p].[void(cb=){
    loop{
      index i = 0;
      if(#cb == 0) cb.new(1);
      ^%char line = cb[#cb-1..-1];
      int w = .fnt.debugFont~textWidth(line<>);
      ~$void(char) appendChar = [void(char c){
        w += .fnt.debugFont~charWidth(c) + .fnt.debugFont~spacingx;
        if(w > .cfg.Width){
          w = .fnt.debugFont~charWidth(c) + .fnt.debugFont~spacingx;
          cb.new[-1];
          line = cb[#cb-1..-1];
        }
        line<> .= c;
      }];
      while;
    do:
      switch(text[i]){
      case '\n':
        cb.new[-1];
        line = cb[#cb-1..-1];
        w = 0;
      case '\t':
        loop{index j = 0, n = 8 - #line<>%8; do:
          line<> .= ' ';
          w += .fnt.debugFont~sizex + .fnt.debugFont~spacingx;
          j++;
        while j < n:}
      default:
        appendChar(:text[i]:);
      }
      i++;
    while i < #text:}
    if(#cb > 10){
      ^%char tmp = cb[#cb-10..-1];
      cb.new(0);
      cb .= tmp;
    }
  }];
}

void appendToClipboard(int p, ^/char formatText, ^&.Var vars)
{
  &.s.Format fm.set(formatText);
  vars:<-[void(i){
    branch{
    cond i.typ == .VarTy::Float:
      fm.f(i.toF());
    else:
      fm.d(i.toI());
    }
  }];
  ^/char tmp = .s.join(\n, .s.split("\n", fm.out));
  tmp = .s.join(\t, .s.split("\t", tmp));
  tmp = .s.join(\\, .s.split("\\", tmp));
  .appendClipboardText(p, tmp);
}

|StTy
{
  S=0x1, C=0x2, A=0x4, L=0x8, N=0x10, U=0x20//L->D N->F U->P
}
const int SCA = (int)StTy::S | (int)StTy::C |(int)StTy::A;
|AtTy
{
  NA=   0x40, NT=   0x80, NP=  0x100,
  SA=  0x200, ST=  0x400, SP=  0x800,
  HA= 0x1000, HT= 0x2000, HP= 0x4000
}
const int ATP =
  (int)AtTy::NA | (int)AtTy::NT |(int)AtTy::NP
  | (int)AtTy::SA | (int)AtTy::ST |(int)AtTy::SP
  | (int)AtTy::HA | (int)AtTy::HT |(int)AtTy::HP;
|MovTy
{
  I=0x8000, A, H=0x10000, U//I->- H->+
}
|AnimTy
{
  Light, Medium, Hard, Back, Up, Diagup, Unknown
}
|PriTy
{
  Hit, Miss, Dodge
}
|ReactTy
{
  Non, High, Low, Trip, Unknown
}
&Fall
{
  public |.AnimTy animtype;
  public float xvelocity;
  public float yvelocity;
  public int recover;
  public int recovertime;
  public int damage;
  public int kill;
  public int envshake_time;
  public float envshake_freq;
  public int envshake_ampl;
  public float envshake_phase;
  public void clear()
  {
    `animtype = .AnimTy::Unknown;
    `xvelocity = 0.0/0.0;
    `yvelocity = -4.5;
    `recover = 0;
    `recovertime = 0;
    `damage = 0;
    `kill = 0;
    `envshake_time = 0;
    `envshake_freq = 0.0;
    `envshake_ampl = 0;
    `envshake_phase = 0.0;
  }
  public void setDefault()
  {
    `animtype = .AnimTy::Unknown;
    `xvelocity = 0.0/0.0;
    `yvelocity = -4.5;
    `recover = 1;
    `recovertime = 4;
    `damage = 0;
    `kill = 1;
    `envshake_time = 0;
    `envshake_freq = 60.0;
    `envshake_ampl = -4;
    `envshake_phase = 0.0/0.0;
  }
}
&Hitdef
{
  public int attr;
  public int reversal_attr;
  public int hitflag;
  public int guardflag;
  public int affectteam;
  public |.AnimTy animtype;
  public |.AnimTy air_animtype;
  public int priority;
  public |.PriTy bothhittype;
  public int hitdamage;
  public int guarddamage;
  public int pausetime;
  public int shaketime;
  public int guard_pausetime;
  public int guard_shaketime;
  public int sparkno;
  public int guard_sparkno;
  public float sparkx;
  public float sparky;
  public int hitsoundg;
  public int hitsoundn;
  public int guardsoundg;
  public int guardsoundn;
  public |.ReactTy ground_type;
  public |.ReactTy air_type;
  public int ground_slidetime;
  public int guard_slidetime;
  public int ground_hittime;
  public int guard_hittime;
  public int air_hittime;
  public int guard_ctrltime;
  public int airguard_ctrltime;
  public int guard_dist;
  public float yaccel;
  public float ground_velocityx;
  public float ground_velocityy;
  public float guard_velocity;
  public float air_velocityx;
  public float air_velocityy;
  public float airguard_velocityx;
  public float airguard_velocityy;
  public float ground_cornerpush_veloff;
  public float air_cornerpush_veloff;
  public float down_cornerpush_veloff;
  public float guard_cornerpush_veloff;
  public float airguard_cornerpush_veloff;
  public int air_juggle;
  public int p1sprpriority;
  public int p2sprpriority;
  public int p1getp2facing;
  public int p1facing;
  public int p2facing;
  public int p1stateno;
  public int p2stateno;
  public int p2getp1state;
  public int forcestand;
  public int ground_fall;
  public int air_fall;
  public float down_velocityx;
  public float down_velocityy;
  public int down_hittime;
  public int down_bounce;
  public int id;
  public int chainid;
  public int nochainid1;
  public int nochainid2;
  public int hitonce;
  public int numhits;
  public int hitgetpower;
  public int guardgetpower;
  public int hitgivepower;
  public int guardgivepower;
  public int palfx_time;
  public int palfx_mulr;
  public int palfx_mulg;
  public int palfx_mulb;
  public int palfx_addr;
  public int palfx_addg;
  public int palfx_addb;
  public int palfx_amplr;
  public int palfx_amplg;
  public int palfx_amplb;
  public int palfx_cycletime;
  public int palfx_color;
  public int palfx_invertall;
  public int envshake_time;
  public float envshake_freq;
  public int envshake_ampl;
  public float envshake_phase;
  public float mindistx;
  public float maxdistx;
  public float mindisty;
  public float maxdisty;
  public float snapx;
  public float snapy;
  public int snapt;
  public &.Fall fall;
  public bool kill;
  public bool guard_kill;
  public bool forcenofall;
  public bool lhit;
  public int player;
  public void clear()
  {
    `attr = 0;
    `reversal_attr = 0;
    `hitflag = (int).StTy::S | (int).StTy::C | (int).StTy::A | (int).StTy::N;
    `guardflag = 0;
    `affectteam = 1;
    `animtype = .AnimTy::Light;
    `air_animtype = .AnimTy::Unknown;
    `priority = 4;
    `bothhittype = .PriTy::Hit;
    `hitdamage = 0;
    `guarddamage = 0;
    `pausetime = 0;
    `shaketime = 0;
    `guard_pausetime = 0;
    `guard_shaketime = 0;
    `sparkno = .com.IERR;
    `guard_sparkno = .com.IERR;
    `sparkx = 0.0;
    `sparky = 0.0;
    `hitsoundg = .com.IERR;
    `hitsoundn = -1;
    `guardsoundg = .com.IERR;
    `guardsoundn = -1;
    `ground_type = .ReactTy::High;
    `air_type = .ReactTy::Unknown;
    `ground_slidetime = 0;
    `guard_slidetime = 0;
    `ground_hittime = 0;
    `guard_hittime = 0;
    `air_hittime = 20;
    `guard_ctrltime = 0;
    `airguard_ctrltime = 0;
    `guard_dist = 0;
    `yaccel = 0.0/0.0;
    `ground_velocityx = 0.0;
    `ground_velocityy = 0.0;
    `guard_velocity = 0.0/0.0;
    `air_velocityx = 0.0;
    `air_velocityy = 0.0;
    `airguard_velocityx = 0.0/0.0;
    `airguard_velocityy = 0.0/0.0;
    `ground_cornerpush_veloff = 0.0/0.0;
    `air_cornerpush_veloff = 0.0/0.0;
    `down_cornerpush_veloff = 0.0/0.0;
    `guard_cornerpush_veloff = 0.0/0.0;
    `airguard_cornerpush_veloff = 0.0/0.0;
    `air_juggle = 0;
    `p1sprpriority = 1;
    `p2sprpriority = 0;
    `p1getp2facing = 0;
    `p1facing = 0;
    `p2facing = 0;
    `p1stateno = -1;
    `p2stateno = -1;
    `p2getp1state = 0;
    `forcestand = .com.IERR;
    `ground_fall = 0;
    `air_fall = .com.IERR;
    `down_velocityx = 0.0/0.0;
    `down_velocityy = 0.0/0.0;
    `down_hittime = 0;
    `down_bounce = 0;
    `id = 0;
    `chainid = -1;
    `nochainid1 = -1;
    `nochainid2 = -1;
    `hitonce = 0;
    `numhits = 1;
    `hitgetpower = .com.IERR;
    `guardgetpower = .com.IERR;
    `hitgivepower = .com.IERR;
    `guardgivepower = .com.IERR;
    `palfx_time = 0;
    `palfx_mulr = 256;
    `palfx_mulg = 256;
    `palfx_mulb = 256;
    `palfx_addr = 0;
    `palfx_addg = 0;
    `palfx_addb = 0;
    `palfx_amplr = 0;
    `palfx_amplg = 0;
    `palfx_amplb = 0;
    `palfx_cycletime = 0;
    `palfx_color = 256;
    `palfx_invertall = 0;
    `envshake_time = 0;
    `envshake_freq = 60.0;
    `envshake_ampl = -4;
    `envshake_phase = 0.0/0.0;
    `mindistx = 0.0/0.0;
    `maxdistx = 0.0/0.0;
    `mindisty = 0.0/0.0;
    `maxdisty = 0.0/0.0;
    `snapx = 0.0/0.0;
    `snapy = 0.0/0.0;
    `snapt = 0;
    `fall.setDefault();
    `kill = true;
    `guard_kill = true;
    `forcenofall = false;
    `lhit = false;
    `player = -1;
  }
  public void invalidate(|.StTy stateType)
  {
    `attr &= !63;
    `attr |= (int)stateType | (int)0x80000000;
    `reversal_attr |= (int)0x80000000;
    `lhit = false;
  }
}
&HitBy
{
  public &ByData
  {
    public int id;
    public int juggle;
    public void set(int id, int juggle)
    {
      `id = id;
      `juggle = juggle;
    }
  }
  public %&ByData by;
  public int hitf1;
  public int hitt1;
  public int hitf2;
  public int hitt2;
  public int attr;
  public int typ;
  public int airanimtype;
  public int groundanimtype;
  public int airtype;
  public int groundtype;
  public int damage = 0;
  public int hitcount;
  public int fallcount;
  public int hitshaketime;
  public int hittime;
  public int slidetime;
  public int ctrltime;
  public float xvel;
  public float yvel;
  public float yaccel;
  public int hitid;
  public float xoff;
  public float yoff;
  public &.Fall fall;
  public int player;
  public bool fallf;
  public bool guarded;
  public bool p2getp1state;
  public bool forcestand;
  public void clear()
  {
    `by.new(0);
    `hitf1 = 0;
    `hitt1 = 0;
    `hitf2 = 0;
    `hitt2 = 0;
    `attr = 0;
    `typ = -1;
    `airanimtype = 0;
    `groundanimtype = 0;
    `airtype = 0;
    `groundtype = 0;
    `hitcount = 0;
    `fallcount = 0;
    `hitshaketime = 0;
    `hittime = -1;
    `slidetime = 0;
    `ctrltime = 0;
    `xvel = 0.0;
    `yvel = 0.0;
    `yaccel = 0.0/0.0;
    `hitid = -1;
    `fall.clear();
    `player = -1;
    `fallf = false;
    `guarded = false;
    `p2getp1state = false;
    `forcestand = false;
  }
  public void clearOff()
  {
    `xoff = 0.0;
    `yoff = 0.0;
  }
  /float getYaccel()
  {
    ret .m.isnan(`yaccel) ? 0.35 : `yaccel;
  }
  /bool byidMatch(int id)
  {
    loop{index i = 0; while; do:
      if(`by[i].id == id) ret true;
      i++;
    while i < #`by:
    }
    ret false;
  }
  /int getJuggle(int id, int defval)
  {
    loop{index i = 0; while; do:
      if(`by[i].id == id) ret `by[i].juggle;
      i++;
    while i < #`by:
    }
    ret defval;
  }
  public void dropByid(int id)
  {
    loop{index i = 0; while; do:
      if(`by[i].id == id){
        %&`ByData tmp .= `by[0..i] .= `by[i+1..-1];
        `by = tmp;
        ret ;
      }
      i++;
    while i < #`by:
    }
  }
  public void addByid(int id, int juggle)
  {
    int jgl = `getJuggle(id, juggle);
    `dropByid(id);
    `by.new[-1].set(id, jgl);
  }
}
&HitOverride
{
  public int attr;
  public int stateno;
  public int time;
  public int forceair;
  public int player;
  new()
  {
    `clear();
  }
  public void clear()
  {
    `attr = 0;
    `stateno = -1;
    `time = 0;
    `forceair = 0;
    `player = -1;
  }
}
|MoveContact
{
  Hit, Guarded, Reversed
}
|ProjContact
{
  Hit, Guarded, Cancel
}
&Persistent
{
  public int p = 0;
}
&StateVal
{
  public ^&.Persistent ps;
  public ^^bool wakegawakaranai;
  public int no, prevno;
  public short playerno, hitdefContact;
  public int time;
  public |.StTy typ;
  public |.StTy phy;
  public |.MovTy mov;
  public int juggle;
  public &.Hitdef hit;
  public &.HitBy hb;
  public ^&.HitOverride ho;
  public |.MoveContact mctyp;
  public int mctime;
  public int fallTime;
  new()
  {
    `ho.new(8);
    `clear();
  }
  public void clearWw()
  {
    loop{index i = 0; while; do:
      loop{index j = 0; while; do:
        `wakegawakaranai[i][j] = false;
        j++;
      while j < .wakewakaLength[i]:}
      i++;
    while i < #.wakewakaLength:}
  }
  public void clear()
  {
    `ps.new(0);
    if(#`wakegawakaranai < #.wakewakaLength){
      `wakegawakaranai.new(#.wakewakaLength);
    }
    loop{index i = 0; while; do:
      if(#`wakegawakaranai[i] < .wakewakaLength[i]){
        `wakegawakaranai[i].new(.wakewakaLength[i]);
      }
      i++;
    while i < #.wakewakaLength:}
    `clearWw();
    `no = 0;
    `prevno = 0;
    `playerno = 0;
    `hitdefContact = 0;
    `time = 0;
    `typ = .StTy::S;
    `phy = .StTy::N;
    `mov = .MovTy::I;
    `hit.clear();
    `hb.clear();
    `hb.clearOff();
    loop{index i=0;do:`ho[i].clear();while ++i<#`ho:}
    `mctyp = .MoveContact::Hit;
    `mctime = 0;
    `fallTime = 0;
  }
  public int hitCheck(&.Hitdef hit=, bool guard)
  {
    ret
      (guard && ((int)`typ&hit.guardflag) != 0 ? 2 : 1) * (
        (int)(`typ == .StTy::A ? hit.air_type : hit.ground_type) == 0
        || hit.reversal_attr > 0
        ? (int)-1 : 1);
  }
  public void setHb(&.Hitdef hit=, bool guard, bool combo, int absdamage=)
  {
    bool cmb = combo && !`hb.guarded;
    bool fall = `hb.fallf;
    int hc = `hb.hitcount, fc = `hb.fallcount;
    %&`hb.ByData bi = `hb.by;
    `hb.clear();
    `hb.by = bi;
    `hb.attr = hit.attr;
    `hb.hitid = hit.id;
    `hb.player = hit.player;
    `hb.p2getp1state = hit.p2getp1state != 0;
    `hb.forcestand = hit.forcestand != 0;
    `hb.fall = hit.fall;
    `fallTime = 0;
    `hb.yaccel = hit.yaccel;
    if(hit.forcenofall) fall = false;
    `hb.groundtype = (int)hit.ground_type;
    `hb.airtype = (int)hit.air_type;
    `hb.typ = `typ == .StTy::A ? `hb.airtype : `hb.groundtype;
    `hb.airanimtype = (int)hit.air_animtype;
    `hb.groundanimtype = (int)hit.animtype;
    if(guard && ((int)`typ&hit.guardflag) != 0){
      `hb.hitshaketime = .m.max!int?(0, hit.guard_shaketime);
      `hb.hittime = .m.max!int?(0, hit.guard_hittime);
      `hb.slidetime = hit.guard_slidetime;
      `hb.guarded = true;
      branch{
      cond `typ == .StTy::A:
        `hb.ctrltime = hit.airguard_ctrltime;
        `hb.xvel = hit.airguard_velocityx;
        `hb.yvel = hit.airguard_velocityy;
      else:
        `hb.ctrltime = hit.guard_ctrltime;
        `hb.xvel = hit.guard_velocity;
        `hb.yvel = hit.ground_velocityy;
      }
      absdamage = hit.guarddamage;
      `hb.hitcount = hc;
      ret;
    }
    `hb.hitshaketime = .m.max!int?(0, hit.shaketime);
    `hb.slidetime = hit.ground_slidetime;
    branch{
    cond `typ == .StTy::A:
      `hb.hittime = hit.air_hittime;
      `hb.ctrltime = hit.air_hittime;
      `hb.xvel = hit.air_velocityx;
      `hb.yvel = hit.air_velocityy;
      `hb.fallf = hit.air_fall != 0;
    cond `typ == .StTy::L:
      `hb.hittime = hit.down_hittime;
      `hb.ctrltime = hit.down_hittime;
      `hb.xvel = hit.down_velocityx;
      `hb.yvel = hit.down_velocityy;
      if(hit.down_bounce == 0){
        `hb.fall.xvelocity = 0.0/0.0;
        `hb.fall.yvelocity = 0.0;
      }
    else:
      `hb.hittime = hit.ground_hittime;
      `hb.ctrltime = hit.ground_hittime;
      `hb.xvel = hit.ground_velocityx;
      `hb.yvel = hit.ground_velocityy;
      `hb.fallf = hit.ground_fall != 0;
    }
    if(`hb.hittime < 0) `hb.hittime = 0;
    absdamage = hit.hitdamage;
    `hb.hitcount = cmb ? hc+1 : 1;
    `hb.fallcount = fc;
    `hb.fallf |= fall;
  }
}
const index iLIFE              = 10;
const index iLIFEMAX           = 11;
const index iLIFEMAX2          = 12;
const index iPOWER             = 13;
const index iPOWERMAX          = 14;
const index iPOWERMAX2         = 15;
const index iATTACK            = 16;
const index iDEFENCE           = 17;
const index iLIEDOWN_TIME      = 18;
const index iAIRJUGGLE         = 19;
const index iSPARKNO           = 20;
const index iGUARD_SPARKNO     = 21;
const index iKO_ECHO           = 22;
const index iVOLUME            = 23;
const index iINTPERSISTINDEX   = 24;
const index iFLOATPERSISTINDEX = 25;
const index iGROUND_BACK       = 26;
const index iGROUND_FRONT      = 27;
const index iAIR_BACK          = 28;
const index iAIR_FRONT         = 29;
const index iHEIGHT            = 30;
const index iATTACK_DIST       = 31;
const index iPROJ_ATTACK_DIST  = 32;
const index iPROJ_DOSCALE      = 33;
const index iHEAD_POSX         = 34;
const index iHEAD_POSY         = 35;
const index iMID_POSX          = 36;
const index iMID_POSY          = 37;
const index iSHADOWOFFSET      = 38;
const index iDRAW_OFFSETX      = 39;
const index iDRAW_OFFSETY      = 40;
const index iAIRJUMP_CNT       = 41;
const index iAIRJUMP_NUM       = 42;
const index iAIRJUMP_HEIGHT    = 43;
const index iHITCOUNT          = 44;
const index iUNIQHITCOUNT      = 45;
const index iPAUSEMOVETIME     = 46;
const index iSUPERMOVETIME     = 47;
const index iBINDTIME          = 48;
const index iBINDTOID          = 49;
const index iBINDFACING        = 50;
const index iHITPAUSETIME      = 51;
const index iALPHAS            = 52;
const index iALPHAD            = 53;
const index iRECOVERTIME       = 54;
const index iSPECIALFLAG       = 55;
const index iSYSFLAG           = 56;
const index iZ_WIDTH              = 57;
const index iATTACK_Z_WIDTH_FRONT = 58;
const index iATTACK_Z_WIDTH_BACK  = 59;

const index fX                = 10;
const index fY                = 11;
const index fVX               = 12;
const index fVY               = 13;
const index fFALL_DEFENCE_MUL = 14;
const index fXSCALE           = 15;
const index fYSCALE           = 16;
const index fWALK_FWD         = 17;
const index fWALK_BACK        = 18;
const index fRUN_FWDX         = 19;
const index fRUN_FWDY         = 20;
const index fRUN_BACKX        = 21;
const index fRUN_BACKY        = 22;
const index fJUMP_NEUX        = 23;
const index fJUMP_NEUY        = 24;
const index fJUMP_BACK        = 25;
const index fJUMP_FWD         = 26;
const index fRUNJUMP_BACKX    = 27;
const index fRUNJUMP_BACKY    = 28;
const index fRUNJUMP_FWDX     = 29;
const index fRUNJUMP_FWDY     = 30;
const index fAIRJUMP_NEUX     = 31;
const index fAIRJUMP_NEUY     = 32;
const index fAIRJUMP_BACK     = 33;
const index fAIRJUMP_FWD      = 34;
const index fYACCEL           = 35;
const index fSTAND_FRICTION   = 36;
const index fCROUCH_FRICTION  = 37;
const index fBINDPOSX         = 38;
const index fBINDPOSY         = 39;
const index fANGLE            = 40;
const index fANGLESCALEX      = 41;
const index fANGLESCALEY      = 42;
const index fCLSNXSCALE       = 43;
const index fCLSNYSCALE       = 44;
const index fAIR_GETHIT_GROUNDRECOVERX                 = 45;
const index fAIR_GETHIT_GROUNDRECOVERY                 = 46;
const index fAIR_GETHIT_AIRRECOVER_MULX                = 47;
const index fAIR_GETHIT_AIRRECOVER_MULY                = 48;
const index fAIR_GETHIT_AIRRECOVER_ADDX                = 49;
const index fAIR_GETHIT_AIRRECOVER_ADDY                = 50;
const index fAIR_GETHIT_AIRRECOVER_BACK                = 51;
const index fAIR_GETHIT_AIRRECOVER_FWD                 = 52;
const index fAIR_GETHIT_AIRRECOVER_UP                  = 53;
const index fAIR_GETHIT_AIRRECOVER_DOWN                = 54;
const index fSTAND_FRICTION_THRESHOLD                  = 55;
const index fCROUCH_FRICTION_THRESHOLD                 = 56;
const index fAIR_GETHIT_GROUNDLEVEL                    = 57;
const index fAIR_GETHIT_GROUNDRECOVER_GROUND_THRESHOLD = 58;
const index fAIR_GETHIT_GROUNDRECOVER_GROUNDLEVEL      = 59;
const index fAIR_GETHIT_AIRRECOVER_THRESHOLD           = 60;
const index fAIR_GETHIT_AIRRECOVER_YACCEL              = 61;
const index fAIR_GETHIT_TRIP_GROUNDLEVEL               = 62;
const index fDOWN_BOUNCE_OFFSETX                       = 63;
const index fDOWN_BOUNCE_OFFSETY                       = 64;
const index fDOWN_BOUNCE_YACCEL                        = 65;
const index fDOWN_BOUNCE_GROUNDLEVEL                   = 66;
const index fDOWN_FRICTION_THRESHOLD                   = 67;
const index fWALK_UP_X                                 = 68;
const index fWALK_DOWN_X                               = 69;
const index fRUN_UP_X                                  = 70;
const index fRUN_UP_Y                                  = 71;
const index fRUN_DOWN_X                                = 72;
const index fRUN_DOWN_Y                                = 73;
const index fJUMP_UP_X                                 = 74;
const index fJUMP_DOWN_X                               = 75;
const index fRUNJUMP_UP_X                              = 76;
const index fRUNJUMP_DOWN_X                            = 77;
const index fAIRJUMP_UP_X                              = 78;
const index fAIRJUMP_DOWN_X                            = 79;


const int lsINVISIBLE     = 0b00000000000000000000000000000001;
const int lsNOSTANDGUARD  = 0b00000000000000000000000000000010;
const int lsNOCROUCHGUARD = 0b00000000000000000000000000000100;
const int lsNOAIRGUARD    = 0b00000000000000000000000000001000;
const int lsNOAUTOTURN    = 0b00000000000000000000000000010000;
const int lsNOJUGGLECHECK = 0b00000000000000000000000000100000;
const int lsNOSHADOW      = 0b00000000000000000000000001000000;
const int lsNOWALK        = 0b00000000000000000000000010000000;
const int lsUNGUARDABLE   = 0b00000000000000000000000100000000;
const int lsPOSFREEZEX    = 0b00000000000000000000001000000000;
const int lsPOSFREEZEY    = 0b00000000000000000000010000000000;
const int lsPLAYERPUSH    = 0b00000000000000000000100000000000;
const int lsSCREENBOUND   = 0b00000000000000000001000000000000;
const int lsMOVECAMERAX   = 0b00000000000000000010000000000000;
const int lsMOVECAMERAY   = 0b00000000000000000100000000000000;
const int lsGETHIT        = 0b00000000000000001000000000000000;
const int lsANGLEDRAW     = 0b00000000000000010000000000000000;
const int lsTRANS         = 0b00000000000000100000000000000000;
const int lsFRONTWCHANGE  = 0b00000000000001000000000000000000;
const int lsBACKWCHANGE   = 0b00000000000010000000000000000000;
const int lsFEDGECHANGE   = 0b00000000000100000000000000000000;
const int lsBEDGECHANGE   = 0b00000000001000000000000000000000;
const int lsDESTROY       = 0b00000000010000000000000000000000;

const int lasMask =
  lsNOAUTOTURN | lsNOWALK | lsNOSTANDGUARD | lsNOCROUCHGUARD | lsNOAIRGUARD
  | lsNOSHADOW | lsINVISIBLE | lsUNGUARDABLE | lsNOJUGGLECHECK;

public uint specialFlag;
const uint gsINTRO          = 0b00000000000000000000000000000001;
const uint gsROUNDNOTOVER   = 0b00000000000000000000000000000010;
const uint gsNOBARDISPLAY   = 0b00000000000000000000000000000100;
const uint gsNOBG           = 0b00000000000000000000000000001000;
const uint gsNOFG           = 0b00000000000000000000000000010000;
const uint gsNOKOSLOW       = 0b00000000000000000000000000100000;
const uint gsGLOBALNOSHADOW = 0b00000000000000000000000001000000;
const uint gsNOMUSIC        = 0b00000000000000000000000010000000;
const uint gsTIMERFREEZE    = 0b00000000000000000000000100000000;
const uint gsNOKO           = 0b00000000000000000000001000000000;
const uint gsNOKOSND        = 0b00000000000000000000010000000000;
public bool gs(uint mask)
{
  ret (.specialFlag & mask) == mask;
}

const int sfAIRJUMP         = 0b00000000000000000000000000000001;
const int sfOVER            = 0b00000000000000000000000000000010;
const int sfKO              = 0b00000000000000000000000000000100;
const int sfKO_ROUND_MIDDLE = 0b00000000000000000000000000001000;
const int sfGUARD           = 0b00000000000000000000000000010000;

&PlayerList<_t>
{
  &Node<_t>
  {
    public ^_t c;
    public ^self next;
  }
  ^&Node!_t? top, end;
  public %^_t drawOrder;
  public void clear()
  {
    `top.new(0);
    `end.new(0);
    `drawOrder.new(0);
  }
}

public ^%^&Char chars.new(.com.maxSimul*2);
/^%&Projectile projs.new(#chars);
/^%&Explod explods.new(#chars);
^&.tbl.IntTable!int, &Char::State? states.new(#chars);

void initWwl()
{
  .wakewakaLength.new(#.chars);
  .wakewakaLength:<-[void(i=){i = 0;}];
}
initWwl();


^%index expdrawlist.new(#.chars), topexpdrawlist.new(#.chars);

void delIL(%index l=, index i)
{
  ^index l1 = l[0..i], l2 = l[i+1..-1];
  l.new(0);
  l .= l1 .= l2;
}

void insIL(%index l=, index i, index x)
{
  ^index l1 = l[0..i], l2 = l[i..-1];
  l.new(0);
  l .= l1 .= x .= l2;
}

&RdCacheInfo
{
  public int n, pn, hi;
}
%&RdCacheInfo playerid;

public &CharGlobalInfo
{
  public ^/char def, displayname, author, nameLow, authorLow;
  public ^/char sprite;
  public ^/char anim;
  public ^/char sound;
  public ^^/char pal;
  public ^index palkeymap;
  public ^&.sff.Sff sf;
  public ^&.snd.Snd sn;
  public %&.act.Action actionList;
  public &.tbl.IntTable!int, &.act.Action? actionTable;
  public int palno, drawpalno;
  public ^bool palExist, palSelectable;
  public short mver0 = 0, mver1 = 0;
  public |.ProjContact pctyp;
  public int pctime, pcid;
  public int unhittable;
  new()
  {
    `clearPCTime();
  }
  public void clearPCTime()
  {
    `pctyp = .ProjContact::Hit;
    `pctime = -1;
    `pcid = 0;
  }
}
public ^&CharGlobalInfo cgi.new(#.chars);

public ^&.fgt.Fight fight;
public bool roundEnd()
{
  ret .com.intro < -.fight~ro.over_hittime;
}


public &PlayerList!&Char? players;
public int id = cfg.HelperMax;
/int pause = 0, pausetime = 0, pausebg = 0, pauseendcmdbuftime = 0;
/int super = 0, supertime = 0, superpausebg = 0, superendcmdbuftime = 0;
int pauseplayer = -1, superplayer = -1;
^&.act.Action superanim;
^&.com.PalFX superpmap.new(1);
float superposx = 0.0, superposy = 0.0;
int superfacing = 1;
int superdarken = 1;
float superp2defmul = 1.0;
/int envcol_time = 0;
/int envcol_under = 0;
int envcol_r = 255;
int envcol_g = 255;
int envcol_b = 255;

&ModifyExplod
{
  public int id;
  public int bindtime;
  public float scalex;
  public float scaley;
  public int removeongethit;
  public int removetime;
  public float velocityx;
  public float velocityy;
  public float accelx;
  public float accely;
  public int sprpriority;
  public int postype;
  public float offsetx;
  public float offsety;
  public int relativef;
  public int vfacing;
  public int shadowr;
  public int shadowg;
  public int shadowb;
  public int ontop;
  public int alphas;
  public int alphad;
  public int supermovetime;
  public int pausemovetime;
  public float angle;
  new()
  {
    `clear();
  }
  public void clear()
  {
    `id = -1;
    `bindtime = .com.IERR;
    `scalex = 0.0/0.0;
    `scaley = 0.0/0.0;
    `removeongethit = .com.IERR;
    `removetime = .com.IERR;
    `velocityx = 0.0/0.0;
    `velocityy = 0.0/0.0;
    `accelx = 0.0/0.0;
    `accely = 0.0/0.0;
    `sprpriority = .com.IERR;
    `postype = .com.IERR;
    `offsetx = 0.0/0.0;
    `offsety = 0.0/0.0;
    `relativef = .com.IERR;
    `vfacing = .com.IERR;
    `shadowr = .com.IERR;
    `shadowg = .com.IERR;
    `shadowb = .com.IERR;
    `ontop = .com.IERR;
    `alphas = .com.IERR;
    `alphad = .com.IERR;
    `supermovetime = .com.IERR;
    `pausemovetime = .com.IERR;
    `angle = 0.0/0.0;
  }
}
public &Explod
{
  public int id;
  public int bindtime;
  public float scalex;
  public float scaley;
  public int time;
  public int removeongethit;
  public int removetime;
  public float velocityx;
  public float velocityy;
  public float accelx;
  public float accely;
  public int sprpriority;
  public int postype;
  public float offsetx;
  public float offsety;
  public int relativef;
  public float x;
  public float y;
  public int facing;
  public int vfacing;
  public int shadowr;
  public int shadowg;
  public int shadowb;
  public int supermovetime;
  public int pausemovetime;
  public ^&.act.Action ani;
  public int ontop;
  public int alphas;
  public int alphad;
  public int ownpal;
  public int player;
  public int bindid;
  public int ignorehitpause;
  public float angle;
  public float ticOldX, ticNewX;
  public float ticOldY, ticNewY;
  public ^&.com.PalFX palfx;
  new()
  {
    `clear();
  }
  public void clear()
  {
    `id = .com.IERR;
    `bindtime = 0;
    `scalex = 1.0;
    `scaley = 1.0;
    `time = 0;
    `removeongethit = 0;
    `removetime = -2;
    `velocityx = 0.0;
    `velocityy = 0.0;
    `accelx = 0.0;
    `accely = 0.0;
    `sprpriority = 0;
    `postype = 0;
    `offsetx = 0.0;
    `offsety = 0.0;
    `relativef = 1;
    `x = 0.0;
    `y = 0.0;
    `facing = 1;
    `vfacing = 1;
    `shadowr = 0;
    `shadowg = 0;
    `shadowb = 0;
    `supermovetime = 0;
    `pausemovetime = 0;
    `ani.new(0);
    `ontop = 0;
    `alphas = .com.IERR;
    `alphad = .com.IERR;
    `ownpal = 0;
    `player = -1;
    `bindid = -1;
    `ignorehitpause = 1;
    `angle = 0.0;
    `ticOldX = `ticNewX = `x;
    `ticOldY = `ticNewY = `y;
    `palfx.new(0);
  }
  public void setX(float x)
  {
    `x = `ticOldX = `ticNewX = x;
  }
  public void setY(float y)
  {
    `y = `ticOldY = `ticNewY = y;
  }
}
public &Projectile
{
  public &.Hitdef hit;
  public int id;
  public int anim;
  public int hitanim;
  public int remanim;
  public int cancelanim;
  public float scalex;
  public float scaley;
  public float clsnscalex;
  public float clsnscaley;
  public int remove;
  public int removetime;
  public float velocityx;
  public float velocityy;
  public float remvelocityx;
  public float remvelocityy;
  public float accelx;
  public float accely;
  public float velmulx;
  public float velmuly;
  public int hits;
  public int misstime;
  public int priority;
  public int prioritypoint;
  public int sprpriority;
  public int edgebound;
  public int stagebound;
  public int heightboundt;
  public int heightboundb;
  public float x;
  public float y;
  public int facing;
  public int shadowr;
  public int shadowg;
  public int shadowb;
  public int supermovetime;
  public int pausemovetime;
  public ^&.act.Action ani;
  public int timemiss, hitpause;
  public float ticOldX, ticNewX;
  public float ticOldY, ticNewY;
  public &.AfterImage aimg;
  public ^&.com.PalFX palfx;
  new()
  {
    `clear();
  }
  public void clear()
  {
    `hit.clear();
    `id = .com.IERR;
    `anim = 0;
    `hitanim = -1;
    `remanim = .com.IERR;
    `cancelanim = .com.IERR;
    `scalex = 1.0;
    `scaley = 1.0;
    `clsnscalex = 1.0;
    `clsnscaley = 1.0;
    `remove = 1;
    `removetime = -1;
    `velocityx = 0.0;
    `velocityy = 0.0;
    `remvelocityx = 0.0;
    `remvelocityy = 0.0;
    `accelx = 0.0;
    `accely = 0.0;
    `velmulx = 1.0;
    `velmuly = 1.0;
    `hits = 1;
    `misstime = 0;
    `priority = 1;
    `prioritypoint = 1;
    `sprpriority = 3;
    `edgebound = 40;
    `stagebound = 40;
    `heightboundt = -240;
    `heightboundb = 1;
    `x = 0.0;
    `y = 0.0;
    `facing = 1;
    `shadowr = 0;
    `shadowg = 0;
    `shadowb = 0;
    `supermovetime = 0;
    `pausemovetime = 0;
    `ani.new(0);
    `timemiss = 0;
    `hitpause = 0;
    `ticOldX = `ticNewX = `x;
    `ticOldY = `ticNewY = `y;
    `aimg.clear();
    `palfx.new(0);
  }
  public void setX(float x)
  {
    `x = `ticOldX = `ticNewX = x;
  }
  public void setY(float y)
  {
    `y = `ticOldY = `ticNewY = y;
  }
  public void remvel()
  {
    if(#`ani > 0) `ani~ani.updateSprite();
    `velocityx = `remvelocityx;
    `velocityy = `remvelocityy;
    `accelx = `accely = 0.0;
    `velmulx = `velmuly = 1.0;
    `anim = -1;
    if(`hits >= 0) `hits = -1;
  }
  public void update(int playerNo)
  {
    if(.com.tickFrame()){
      branch{
      cond `anim >= 0:
        branch{
        cond `hits < 0 && `remove != 0:
          branch{
          cond `hits == -1:
            if(`hitanim != `anim){
              `ani = .chars[playerNo][0]~getAction(`hitanim);
            }
          else:
            if(`cancelanim != `anim){
              `ani = .chars[playerNo][0]~getAction(`cancelanim);
            }
          }
        cond
          `x < .com.xmin - (float)`edgebound
          || `x > .com.xmax + (float)`edgebound
          || (
            `velocityx * (float)`facing < 0.0
            && `x < .com.cam.xMin - (float)`stagebound)
          || (
            `velocityx*(float)`facing > 0.0
            && `x > .com.cam.xMax + (float)`stagebound)
          || (`velocityy > 0.0 && `y > (float)`heightboundb)
          || (`velocityy < 0.0 && `y < (float)`heightboundt)
          || `removetime == 0
          || (`removetime <= -2 && (#`ani == 0 || `ani~ani.loopend))
          :
          if(`remanim != `anim) `ani = .chars[playerNo][0]~getAction(`remanim);
        else:
          break;
        comm:
          `remvel();
          break, else;
        }
      else:
        if(#`ani > 0 && (`ani~ani.totaltime <= 0 || `ani~ani.animTime() == 0)){
          `ani.new(0);
        }
        if(#`ani == 0 && `id >= 0) `id = !`id;
      }
    }
    if(`paused(playerNo) || `hitpause != 0) ret;
    if(.com.tickFrame()){
      `ticOldX = `x;
      `ticNewX = `x + `velocityx*(float)`facing;
      `ticOldY = `y;
      `ticNewY = `y + `velocityy;
    }
    float sp = .com.tickInterpola();
    `x = `ticNewX - (`ticNewX - `ticOldX) * (1.0 - sp);
    `y = `ticNewY - (`ticNewY - `ticOldY) * (1.0 - sp);
    if(.com.tickNextFrame()){
      `velocityx += `accelx;
      `velocityy += `accely;
      `velocityx *= `velmulx;
      `velocityy *= `velmuly;
      if(`velocityx < 0.0){
        `facing *= -1;
        `velocityx *= -1.0;
        `accelx *= -1.0;
      }
    }
  }
  public bool hitCheck(&.Projectile pr=)
  {
    if(#pr.ani == 0 || #pr.ani~ani.frames == 0) ret false;
    if(#`ani == 0 || #`ani~ani.frames == 0) ret false;
    ^&.act.Frame frm;
    ^&.act.Rect clsn1 = pr.ani~ani.currentFrame()=>frm$frm~clsn2();
    ^&.act.Rect clsn2 = `ani~ani.currentFrame()=>frm$frm~clsn2();
    &.ClsnHantei ch.set(
      #pr.clsnscalex, pr.clsnscaley, pr.x, pr.y,
      (float)pr.facing*pr.clsnscalex > 0.0 ? .pLrSet : .mLrSet,
      #`clsnscalex, `clsnscaley, `x, `y,
      (float)`facing*`clsnscalex > 0.0 ? .pLrSet : .mLrSet);
    loop{index i = 0; while; do:
      loop{index j = 0; while; do:
        if(ch.hantei(clsn1[i], clsn2[j])) ret true;
        j++;
      while j < #clsn2:}
      i++;
    while i < #clsn1:}
    ret false;
  }
  public void projClsn(int playerNo)
  {
    void cancel(
      int prioritypoint=, int priority, int hits=, int oppprioritypoint)
    {
      if(oppprioritypoint > prioritypoint || hits <= 0){
        hits = -2;
        ret;
      }
      branch{
      cond oppprioritypoint == prioritypoint:
        branch{
        cond hits <= 1:
          hits = -2;
        else;
          hits = 3*hits / 4 - 1;
          if(hits <= 0) break, else;
          prioritypoint = priority;
        }
      else:
        prioritypoint--;
      }
    }
    loop{index i = 0; while; do:
      loop{
        index j = 0;
        while;
      do:
        if(
          .projs[i][j].id < 0 || (
            .projs[i][j].hit.affectteam != 0 && (
              (playerNo&1) != (i&1)) != (.projs[i][j].hit.affectteam > 0))
          ) continue;
        if(.projs[i][j].hits >= 0 && `hitCheck(.projs[i][j]=)){
          int pp = `prioritypoint;
          cancel(
            `prioritypoint=, `priority, `hits=, .projs[i][j].prioritypoint);
          cancel(
            .projs[i][j].prioritypoint=, .projs[i][j].priority,
            .projs[i][j].hits=, pp);
        }
      continue:
        j++;
      while `hits >= 0 && j < #.projs[i]:}
      i++;
    while `hits >= 0 && i < playerNo:}
  }
  bool paused(int playerNo)
  {
    if(!.chars[playerNo]<>~isPaused()) branch{
    cond .super > 0:
      if(`supermovetime == 0) ret true;
    cond .pause > 0:
      if(`pausemovetime == 0) ret true;
    }
    ret false;
  }
  public void tick(int playerNo)
  {
    if(`timemiss < 0){
      `timemiss = !`timemiss;
      if(`hits >= 0){
        branch{
        cond `misstime <= 0 && `hitpause == 0:
          `hits = -1;
        else:
          `hits--;
          if(`hits <= 0) `hits = -1;
        }
      }
      `hit.air_juggle = 0;
    }
    if(`hits < 0) `hitpause = 0;
    if(`paused(playerNo)) ret;
    if(`hitpause <= 0){
      if(`removetime > 0) `removetime--;
      if(`timemiss > 0) `timemiss--;
    }
  }
  public void anime(bool oVer, int playerNo)
  {
    bool notpause = `hitpause <= 0 && !`paused(playerNo);
    if(.com.tickFrame() && #`ani > 0 && notpause){
      `ani~ani.updateSprite();
    }
    if(.com.clsndraw && #`ani > 0){
      ^&.act.Frame frm = `ani~ani.drawFrame();
      if(#frm == 0) break;
      ^&.act.Rect clsn = frm~clsn1();
      if(#clsn > 0){
        .drawc1.new[-1].set(
          clsn, `x, `y, (float)`facing*`clsnscalex, `clsnscaley);
      }
      clsn = frm~clsn2();
      if(#clsn > 0){
        .drawc2.new[-1].set(
          clsn, `x, `y, (float)`facing*`clsnscalex, `clsnscaley);
      }
    }
    if(.com.tickNextFrame() && (notpause || !`paused(playerNo))){
      if(#`ani > 0 && notpause) `ani~ani.action();
      branch{
      cond `hitpause > 0:
        `hitpause--;
      else:
        if(`supermovetime > 0) `supermovetime--;
        if(`pausemovetime > 0) `pausemovetime--;
      }
    }
    if(#`ani > 0 && #`ani~ani.spr > 0){
      bool br = playerNo == .superplayer;
      .addAnimList(
        .anims=, `ani, `sprpriority, `x, `y, false, (float)`facing*`scalex,
        `scaley, 0.0,  oVer, 1.0, 1.0, -1, 0, br, `palfx,
        `shadowr<<16 | (`shadowg&255)<<8 | (`shadowb&255), 256, 0.0, 0.0);
      `aimg.recAndAddAL(
        `ani<>=, `sprpriority, `x, `y, (float)`facing*`scalex, `scaley,
        0.0, .cgi[playerNo].mver0 != 1, 1.0, 1.0,
        .com.tickNextFrame() && notpause, br, `palfx);
    }
  }
}
public &Char
{
  public void dummy(){}
  type stateMethod_t = method dummy.signature;
  public &State
  {
    public .Char::stateMethod_t stateDef = .Char::dummy, state = .Char::dummy;
  }
  public ^/char name;
  public ^&.com.PalFX palfx;
  public ^&.act.Action ani;
  public ^int ivar, sysivar;
  public ^float fvar, sysfvar;
  public ^&.cmd.CommandList cmd;
  public &.StateVal stVal;
  public &.AfterImage aimg;
  public int id, helperindex, helperid, parentindex, key;
  public %int children;
  public %int targets, targetsOfHit;
  public byte playerno;
  public byte facing;
  public bool keyctrl;
  public bool player;
  public bool inguarddist;
  public byte p1facing, animpno;
  public bool cs1tmp;
  public bool ctrl, standby;
  public byte hittmp, acttmp;
  public byte atktmp;
  public byte minus;
  public bool pushed;
  public byte ho;
  public int sprpriority;
  public int animno;
  public int getcombo;
  public float frontw, backw, fedge, bedge;
  public float attackmul, attackmult, defencemul, defencemult, attackdist;
  public float offsetx, offsety;
  public float veloff;
  public float ticOldX, drawX, ticOldY, drawY;
  public ^%&.RdCacheInfo enemyn;
  public ^&.act.Frame curFrame;
  public %&.snd.Sound sounds;
  public index cpucmd = -1;
  public method$void() stateDef = dummy, state = dummy, state_1 = dummy,
    state_2 = dummy, state_3 = dummy, state_i1 = dummy;
  type action_t = &.act.Action;
  &.sff.AirFileMethods!self? airFileMethods;
  new()
  {
    `ivar.new(60);
    `sysivar.new(60);
    `fvar.new(40);
    `sysfvar.new(80);
    `enemyn.new(2);
    `clearVal();
  }
  public void rootInit()
  {:<-
    method$void() init = `dummy;
    <consteval>(init=, "`stateInit" + ''`playerno + "P");
    init(::);
  }
  void copyParent(`self c=)
  {
    `parentindex = c.helperindex;
    `name = c.name + "'s helper";
    `key = c.key;
    `state_1 = c.state_1;
    `state_2 = c.state_2;
    `state_3 = c.state_3;
    `state_i1 = c.state_i1;
    .s.copy!int?(`sysivar[10..-1], c.sysivar[10..-1]);
    .s.copy!float?(`sysfvar[10..-1], c.sysfvar[10..-1]);
    `sysivar[.iLIFE] = `sysivar[.iLIFEMAX];
    `sysivar[.iPOWER] = 0;
    `clearSpSysVar();
  }
  public void enemynClear()
  {
    `enemyn[0].new(0);
    `enemyn[1].new(0);
  }
  public void clearSpSysVar()
  {
    `rangeSetSysIVar(0, 4, 0);
    `rangeSetSysFVar(0, 4, 0.0);
    `sysivar[.iAIRJUMP_CNT] = 0;
    `sysivar[.iHITCOUNT] = 0;
    `sysivar[.iUNIQHITCOUNT] = 0;
    `sysivar[.iPAUSEMOVETIME] = 0;
    `sysivar[.iSUPERMOVETIME] = 0;
    `sysivar[.iBINDTIME] = 0;
    `sysivar[.iBINDTOID] = -1;
    `sysivar[.iHITPAUSETIME] = 0;
    `sysfvar[.fANGLE] = 0.0;
    `sysfvar[.fANGLESCALEX] = 1.0;
    `sysfvar[.fANGLESCALEY] = 1.0;
    `sysivar[.iALPHAS] = 255;
    `sysivar[.iALPHAD] = 0;
    `sysivar[.iRECOVERTIME] = 0;
    `sysivar[.iSYSFLAG] = 0;
    `ctrl = false;
    `standby = false;
    `sprpriority = 0;
    `getcombo = 0;
    `veloff = 0.0;
    `ticOldX = `drawX = `sysfvar[.fX];
    `ticOldY = `drawY = `sysfvar[.fY];
    branch{
    cond `helperindex == 0:
      branch{
      cond .com.rexisted[`playerno&1] > 0:
        `palfx~clear();
      else:
        `palfx.new(1);
      }
    else:
      `palfx.new(0);
    }
    `aimg.timegap = -1;
    `frontw = `defFW();
    `backw = `defBW();
    `fedge = `bedge = 0.0;
    `attackmul = (float)`sysivar[.iATTACK] / 100.0;
	`attackmult = 1.0;
    `defencemul = (float)`sysivar[.iDEFENCE] / 100.0;
	`defencemult = 1.0;
    `enemynClear();
    `targets.new(0);
    `cpucmd = -1;
  }
  public void clearVal()
  {
    `ani.new(0);
    `cmd.new(0);
    `curFrame.new(0);
    `stVal.clear();
    `rangeSetSysIVar(0, #`sysivar-1, 0);
    `rangeSetSysFVar(0, #`sysfvar-1, 0.0);
    `rangeSetIVar(0, #`ivar-1, 0);
    `rangeSetFVar(0, #`fvar-1, 0.0);
    `key = -1; `id = -1; `playerno = -1; `helperindex = -1;
    `helperid = 0; `parentindex = .com.IERR;
    `facing = 1;
    `keyctrl = false;
    `player = false;
    `inguarddist = false;
    `p1facing = 0;
    `animpno = -1;
    `animno = 0;
    `atktmp = 0;
    `hittmp = 0;
    `acttmp = 0;
    `minus = 2;
    `pushed = false;
    `ho = -1;
    `cs1tmp = false;
    `stateDef = `dummy;
    `state = `dummy;
  }
  void clearHitDef()
  {
    `stVal.hit.clear();
  }
  void clearMoveHit()
  {
    `stVal.mctime = 0;
  }
  void clearHitCount()
  {
    `sysivar[.iHITCOUNT] = 0;
    `sysivar[.iUNIQHITCOUNT] = 0;
  }
  public void rangeSetSysIVar(index start, index end, int n)
  {
    if(start < 0) ret;
    loop{index i = start; while; do:
      `sysivar[i] = n;
      i++;
    while i <= end && i < #`sysivar:}
  }
  public void rangeSetSysFVar(index start, index end, float n)
  {
    if(start < 0) ret;
    loop{index i = start; while; do:
      `sysfvar[i] = n;
      i++;
    while i <= end && i < #`sysfvar:}
  }
  public void rangeSetIVar(index start, index end, int n)
  {
    if(start < 0 || end >= #`ivar) ret;
    loop{index i = start; while; do:
      `ivar[i++] = n;
    while i <= end:}
  }
  public void rangeSetFVar(index start, index end, float n)
  {
    if(start < 0 || end >= #`fvar) ret;
    loop{index i = start; while; do:
      `fvar[i++] = n;
    while i <= end:}
  }
  public ^&.act.Action getAction(int no)
  {
    *`ani.self a, act = .cgi[`playerno].actionTable.get(no);
    if(#act > 0){
      a.new(1);
      a~copy(act<>=);
    }
    ret a;
  }
  public ^action_t newAction(int no)
  {
    .cgi[`playerno].actionList.new[-1].no = no;
    *`ani.self act =
      .cgi[`playerno].actionList[#.cgi[`playerno].actionList-1..-1];
    .cgi[`playerno].actionTable.set(no, act);
    ret act;
  }
  public ^&.snd.Sound newChannel(int ch, bool lowpriority)
  {
    index c = .m.min!int?(255, ch);
    if(c >= 0) branch{
    cond lowpriority:
      if(#`sounds > c && #`sounds[c].sound > 0){
        ret .consts.null!&.snd.Sound?();
      }
    comm:
      `sounds.new[c];
      ret `sounds[c..c+1];
    }
    `sounds.new[255];
    loop{index i = 255; do:
      if(#`sounds[i].sound == 0) ret `sounds[i..i+1];
      i--;
    while i >= 0:}
    ret .consts.null!&.snd.Sound?();
  }
  public ^&.Explod newExplod(index idx=)
  {:<-
    ^&.Explod foo(index i)
    {
      .explods[`playerno][i].clear();
      .explods[`playerno][i].id = -1;
      .explods[`playerno][i].player = `id;
      .explods[`playerno][i].palfx = `getPalfx();
      ret .explods[`playerno][i..i+1];
    }
    loop{idx = 0; while; do:
      if(.explods[`playerno][idx].id == .com.IERR) ret foo(idx);
      idx++;
    while idx < #.explods[`playerno]:
      if(idx < .cfg.ExplodMax){
        .explods[`playerno].new[idx];
        ret foo(idx);
      }
    }
    idx = -1;
    ret .consts.null!&.Explod?();
  }
  public void insertExplodEx(index i, int rpg, int rpi)
  {
    if(#.explods[`playerno][i].ani == 0){
      .explods[`playerno][i].id = .com.IERR;
      ret;
    }
    .explods[`playerno][i].[void(e=){
      e.ani~ani.updateSprite();
      if(e.ownpal != 0 && e.ani~ani.sff != .fight~fsf){
        %index remap .= e.palfx~remap;
        e.palfx.new(1);
        e.palfx~remap = remap;
        `remapPalSub(e.palfx, 1, 1, rpg, rpi);
      }
    }];
    branch{
    cond .explods[`playerno][i].ontop != 0:
      loop{
        index ii = 0;
       while;
      do:
        if(.topexpdrawlist[`playerno][ii] < 0){
          .topexpdrawlist[`playerno][ii] = i;
          break, break;
        }
        ii++;
      while ii < #.topexpdrawlist[`playerno]:
        .topexpdrawlist[`playerno] .= i;
      }
    else:
      loop{
        index ii = 0;
        int p;
        while;
      do:
        p = .explods[`playerno][.expdrawlist[`playerno][ii]].player;
        if(p >= `id && (p > `id || .expdrawlist[`playerno][ii] < i)){
          .insIL(.expdrawlist[`playerno]=, ii, i);
          break, break;
        }
        ii++;
      while ii < #.expdrawlist[`playerno]:
        .expdrawlist[`playerno] .= i;
      }
    }
  }
  public void insertExplod(index i)
  {
    `insertExplodEx(i, -1, 0);
  }
  public ^&.Projectile newProj()
  {
    loop{index i = 0; while; do:
      if(.projs[`playerno][i].id < 0){
        .projs[`playerno][i].clear();
        .projs[`playerno][i].id = 0;
        .projs[`playerno][i].palfx = `getPalfx();
        ret .projs[`playerno][i..i+1];
      }
      i++;
    while i < #.projs[`playerno]:
      if(i < .cfg.PlayerProjectileMax){
        .projs[`playerno].new[i].id = 0;
        .projs[`playerno][i].palfx = `getPalfx();
        ret .projs[`playerno][i..i+1];
      }
    }
    ret .consts.null!&.Projectile?();
  }
  public void addTarget(int id)
  {
    if(!`hasTarget(id)) `targets .= id;
  }
  /bool hasTarget(int id)
  {
    loop{index i = 0; while; do:
      if(`targets[i] == id) ret true;
      i++;
    while i < #`targets:}
    ret false;
  }
  /bool hasTargetOfHit(int id)
  {
    loop{index i = 0; while; do:
      if(`targetsOfHit[i] == id) ret true;
      i++;
    while i < #`targetsOfHit:}
    ret false;
  }
  public void removeTarget(int id)
  {
    loop{index i = 0; while; do:
      if(`targets[i] == id){
        %int temp .= `targets[0 .. i] .= `targets[i + 1 .. -1];
        `targets = temp;
        break, break;
      }
      i++;
    while i < #`targets:}
  }
  public void byBindClear()
  {
    if(`isBound()) `setBindTime(0);
  }
  void enemyExplodsRemove(int enemy)
  {
    void enemyExpRemove(^%index drawlist=, bool delI, int id)
    {
      loop{
        index i = #drawlist[`enemy]-1, tmp;
        while;
      do:
        tmp = drawlist[`enemy][i];
        if(tmp < 0) continue;
        if(
          .explods[`enemy][tmp].bindtime != 0
          && .explods[`enemy][tmp].bindid == id)
        {
          .explods[`enemy][tmp].id = .com.IERR;
          branch{
          cond delI:
            .delIL(drawlist[`enemy]=, i);
          else:
            drawlist[`enemy][i] = -1;
          }
        }
      continue:
        i--;
      while i >= 0:}
    }
    enemyExpRemove(.expdrawlist=, true, `id);
    enemyExpRemove(.topexpdrawlist=, false, `id);
  }
  public void outTarget(bool expremove)
  {
    if(`hittmp >= 0){
      loop{
        index i = 0;
        ^`self c;
        while;
      do:
        c = .players.get(`stVal.hb.by[i].id);
        if(#c > 0){
          c~removeTarget(`id);
          if(expremove) `enemyExplodsRemove(c~playerno);
        }
        i++;
      while i < #`stVal.hb.by:}
      `byBindClear();
    }
    `stVal.hb.by.new(0);
  }
  void addChild(int hidx)
  {
    loop{index i = 0; while; do:
      if(`children[i] < 0){
        `children[i] = hidx;
        ret;
      }
      i++;
    while i < #`children:}
    `children .= hidx;
  }
  public ^&.com.PalFX getPalfx()
  {
    if(#`palfx > 0) ret `palfx;
    if(`parentindex < 0){
      `palfx.new(1);
      ret `palfx;
    }
    ret .chars[`playerno][`parentindex]~getPalfx();
  }
  public %index getPalMap()
  {
    ^&.com.PalFX pfx = `getPalfx();
    ret pfx~remap;
  }
  /bool ls(int mask)
  {
    ret (`sysivar[.iSPECIALFLAG] & mask) == mask;
  }
  /bool sf(int mask)
  {
    ret (`sysivar[.iSYSFLAG] & mask) == mask;
  }
  public ^/char load(^/char def)
  {:<-
    void info(&.com.Section sc=)
    {
      ^/char data, err;
      err = sc.getText("name", data=);
      if(#err == 0 && #data > 0) `name = data;
      err = sc.getText("displayname", data=);
      branch{
      cond #err == 0 && #data > 0:
        .cgi[`playerno].displayname = data;
      else:
        .cgi[`playerno].displayname = `name;
      }
      err = sc.getText("author", data=);
      if(#err == 0 && #data > 0) .cgi[`playerno].author = data;
      .cgi[`playerno].nameLow = .s.toLower(`name);
      .cgi[`playerno].authorLow = .s.toLower(.cgi[`playerno].author);
    }
    void files(&.com.Section sc=, bool unicode)
    {
      bool oVer = `mver0() != 1;
      ^/char f(^/char str)
      {
        ^/char s = .com.readFileName(str, `unicode);
        if(`oVer) s = s[0...s.cFind(" "\t, s)];
        ret s;
      }
      ^/char data;
      .cgi[`playerno].[void(c=){
        if(#(data = sc.get("sprite")) > 0) c.sprite = f(data);
        if(#(data = sc.get("anim")) > 0) c.anim = f(data);
        if(#(data = sc.get("sound")) > 0) c.sound = f(data);
        if(#(data = sc.get("pal1")) > 0) c.pal[0] = f(data);
        if(#(data = sc.get("pal2")) > 0) c.pal[1] = f(data);
        if(#(data = sc.get("pal3")) > 0) c.pal[2] = f(data);
        if(#(data = sc.get("pal4")) > 0) c.pal[3] = f(data);
        if(#(data = sc.get("pal5")) > 0) c.pal[4] = f(data);
        if(#(data = sc.get("pal6")) > 0) c.pal[5] = f(data);
        if(#(data = sc.get("pal7")) > 0) c.pal[6] = f(data);
        if(#(data = sc.get("pal8")) > 0) c.pal[7] = f(data);
        if(#(data = sc.get("pal9")) > 0) c.pal[8] = f(data);
        if(#(data = sc.get("pal10")) > 0) c.pal[9] = f(data);
        if(#(data = sc.get("pal11")) > 0) c.pal[10] = f(data);
        if(#(data = sc.get("pal12")) > 0) c.pal[11] = f(data);
      }];
    }
    void keymap(&.com.Section sc=)
    {:<-
      void foo(index k, ^/char p)
      {
        .cgi[`playerno].palkeymap[k] = .com.aton!.cgi<>.palkeymap<>.self?(p)-1;
        if(
          !.m.inRange!index?(
            0, .sff.NumCharPalletes-1, .cgi[`playerno].palkeymap[k]))
        {
          .cgi[`playerno].palkeymap[k] = 0;
        }
      }
      ^/char data;
      if(#(data = sc.get("a")) > 0) foo(0, data);
      if(#(data = sc.get("b")) > 0) foo(1, data);
      if(#(data = sc.get("c")) > 0) foo(2, data);
      if(#(data = sc.get("x")) > 0) foo(3, data);
      if(#(data = sc.get("y")) > 0) foo(4, data);
      if(#(data = sc.get("z")) > 0) foo(5, data);
      if(#(data = sc.get("a2")) > 0) foo(6, data);
      if(#(data = sc.get("b2")) > 0) foo(7, data);
      if(#(data = sc.get("c2")) > 0) foo(8, data);
      if(#(data = sc.get("x2")) > 0) foo(9, data);
      if(#(data = sc.get("y2")) > 0) foo(10, data);
      if(#(data = sc.get("z2")) > 0) foo(11, data);
    }
    bool keymapflg = true;
    ~$void(^/char, &.com.Section=) palette = [palette.signature(sec, sc=){
      branch{
      cond .s.equ(.s.toLower(sec[0..6]), "keymap"):
        if(keymapflg) keymap(sc=);
        keymapflg = false;
      }
    }];
    bool unicode = false;
    bool infoflg = true, filesflg = true;
    ~$void(^^/char, index=) section = [void(^^/char lines, index i=){
      ^/char sec = lines[i];
      ^/char secname = .com.sectionName(sec=);
      if(#secname == 0) ret;
      i++;
      &.com.Section sc.parse(lines, i=);
      branch{
      cond .s.equ(secname, "info"):
        if(infoflg) info(sc=);
        infoflg = false;
      cond .s.equ(secname, "files"):
        if(filesflg) files(sc=, unicode);
        filesflg = false;
      cond .s.equ(secname, "palette "):
        palette(:sec, sc=:);
      }
    }];
    ^/char error;
    .cgi[`playerno].def = def;
    ^char mainbuf = .com.loadText(def, unicode=);
    ^^/char lines = .com.splitLines(mainbuf);
    .s.each!^/char?([void(^/char l=){l=.s.trim(l);}], lines);
    .com.mugenversion(lines, .cgi[`playerno].mver0=, .cgi[`playerno].mver1=);
    `clearDef();
    loop{index i = 0; while; do:
      section(:lines, i=:);
      i++;
    while i < #lines:}
    .cgi[`playerno].sf.new(1);
    if(
      #.com.loadFile(def, .cgi[`playerno].sprite=)=>error <,
      [^/char(^/char f){ret .cgi[`playerno].sf~loadFile(f, true);}] > 0)
    {
      ret def + ":"\r\n + error;
    }
    if(
      #.com.loadFile(def, .cgi[`playerno].anim=)=>error <, [^/char(^/char f){
        ret
          #.com.loadText(f, unicode=)=>mainbuf > 0
          ? "" : .com.FileReadError;
      }] > 0) 
    {
      ret def + ":"\r\n + error;
    }
    lines = .com.splitLines(mainbuf);
    lines:<-[void(l=){l = .s.trim(l);}];
    .cgi[`playerno].actionList.new(0);
    .cgi[`playerno].actionTable.clear();
    loop{index i = 0; while; do:
      `readAction(lines, i=);
      i++;
    while i < #lines:}
    .cgi[`playerno].actionList:<-[void(a=){a.ani.setup(.cgi[`playerno].sf);}];
    .cgi[`playerno].sn.new(1);
    if(
      #.cgi[`playerno].sound > 0
      && #.com.loadFile(def, .cgi[`playerno].sound=)=>error <,
      [^/char(^/char f){ret .cgi[`playerno].sn~loadFile(f);}] > 0)
    {
      ret def + ":"\r\n + error;
    }
    ret "";
  }
  public bool loadPallet(^/char def, int no)
  {
    .cgi[`playerno].palExist.new(.sff.NumCharPalletes);
    branch{
    cond .cgi[`playerno].sf~head.ver0 == 0d1:
      loop{
        index i = 0, tmp = 0;
        ubyte r, g, b;
        ^uint pl;
        .cgi[`playerno].sf~palList.resetRemap();
        while;
      do:
        pl = .cgi[`playerno].sf~palList.get(i);
        branch{
          &.file.File f;
        cond
          #.com.loadFile(def, .cgi[`playerno].pal[i]=)<, [^/char(^/char fn){
            f.open(fn, "rb"); ret f.read!ubyte?(r=) ? "" : "error";
          }] == 0
          :
          loop{
            index j = 255;
            continue;
          do:
            if(!f.read!ubyte?(r=)) break, else;
          continue:
            if(!f.read!ubyte?(g=)) break, else;
            if(!f.read!ubyte?(b=)) break, else;
            pl[j] = (uint)r<<0d16 | (uint)g<<0d8 | (uint)b;
            j--;
          while j >= 0:}
          if(tmp == 0 && i > 0){
            .s.copy!uint?(.cgi[`playerno].sf~palList.get(0), pl);
          }
          tmp = i+1;
          .cgi[`playerno].palExist[i] = true;
        else:
          .cgi[`playerno].palExist[i] = false;
          if(i > 0){
            .cgi[`playerno].sf~palList.palTable.remove(
              (uint)1 << 0d16 | (ushort)(i+1));
          }
        }
        i++;
      while i < .sff.NumCharPalletes:
        if(tmp == 0){
          .cgi[`playerno].sf~palList.palTable.remove((uint)1 << 0d16 | 0x1);
        }
      }
    else:
      loop{int i = 0; while; do:
        .cgi[`playerno].palExist[i] =
          #.cgi[`playerno].sf~palList.palTable.get(
            (uint)1 << 0d16 | (ushort)(i+1))
          > 0;
        i++;
      while i < .sff.NumCharPalletes:}
    }
    .cgi[`playerno].palSelectable.new(.sff.NumCharPalletes);
    .s.each!bool?([void(bool ps=){ps=false;}], .cgi[`playerno].palSelectable);
    loop{int i = 0; while; do:
      loop{
        int startj =
          .cgi[`playerno].palExist[.cgi[`playerno].palkeymap[i]]
          ? .cgi[`playerno].palkeymap[i] : .cgi[`playerno].palkeymap[i] % 6;
        int j = startj;
      do:
        if(.cgi[`playerno].palExist[j]){
          .cgi[`playerno].palSelectable[j] = true;
          break, break;
        }
        j++;
        if(j >= .sff.NumCharPalletes) j = 0;
      while j != startj:}
      i++;
    while i < .sff.NumCharPalletes:}
    .cgi[`playerno].palno = .cgi[`playerno].palkeymap[no-1]+1;
    .cgi[`playerno].drawpalno = `palno();
    loop{
      index starti =
        .cgi[`playerno].palExist[`palno()-1] ? `palno()-1 : (`palno()-1) % 6;
      index i = starti;
    do:
      if(.cgi[`playerno].palExist[i]) loop{index j = 0; while; do:
        if(
          j != `playerno && #.chars[j] > 0
          && .s.equ(.cgi[j].def, .cgi[`playerno].def)
          && .cgi[j].drawpalno == i+1) break;
        j++;
      while j < #.chars:
        .cgi[`playerno].drawpalno = i+1;
        if(!.cgi[`playerno].palExist[`palno()-1]){
          .cgi[`playerno].palno = .cgi[`playerno].drawpalno;
        }
        break, break;
      }
      i++;
      if(i >= .sff.NumCharPalletes) i = 0;
    while i != starti:
      if(!.cgi[`playerno].palExist[`palno()-1]) loop{int i = 0; while; do:
        if(.cgi[`playerno].palExist[i]){
          .cgi[`playerno].palno = .cgi[`playerno].drawpalno = i+1;
          break, break;
        }
        i++;
      while i < .sff.NumCharPalletes:
        .cgi[`playerno].palno = 1;
        .cgi[`playerno].palExist[0] = .cgi[`playerno].palSelectable[0] = true;
      }
    }
    ret true;
  }
  public void clearDef()
  {
    `name = "";
    .cgi[`playerno].displayname = "";
    .cgi[`playerno].author = "";
    .cgi[`playerno].sprite = "";
    .cgi[`playerno].anim = "";
    .cgi[`playerno].sound = "";
    .cgi[`playerno].pal.new(.sff.NumCharPalletes);
    .cgi[`playerno].palkeymap.new(.sff.NumCharPalletes);
    loop{index i = 0; while; do:
      .cgi[`playerno].palkeymap[i] = i;
      i++;
    while i < #.cgi[`playerno].palkeymap:}
  }
  public int gethitAnimtype()
  {
    ret
      `isFall() ? (int)`stVal.hb.fall.animtype : (
        `stVal.typ == .StTy::A
        ? `stVal.hb.airanimtype : `stVal.hb.groundanimtype);
  }
  public void setEnemyWinty()
  {
    if(`helperindex != 0) ret;
    branch{
    cond `stVal.mov != .MovTy::H:
      branch{
      cond `playerno == `stVal.playerno:
        .winty[!`playerno&1] = .fgt.WinTy::Suicide;
      cond (`playerno&1) == (`stVal.playerno&1):
        .winty[!`playerno&1] = .fgt.WinTy::Teammate;
      }
    cond `playerno == `stVal.hb.player:
      .winty[!`playerno&1] = .fgt.WinTy::Suicide;
    cond `stVal.hb.player >= 0 && (`playerno&1) == (`stVal.hb.player&1):
      .winty[!`playerno&1] = .fgt.WinTy::Teammate;
    cond `stVal.hb.guarded:
      .winty[!`playerno&1] = .fgt.WinTy::C;
    cond
      (`stVal.hb.attr&((int).AtTy::HA|(int).AtTy::HT|(int).AtTy::HP))
      != 0
      :
      .winty[!`playerno&1] = .fgt.WinTy::H;
    cond
      (`stVal.hb.attr&((int).AtTy::SA|(int).AtTy::ST|(int).AtTy::SP))
      != 0
      :
      .winty[!`playerno&1] = .fgt.WinTy::S;
    cond
      (`stVal.hb.attr&((int).AtTy::NT|(int).AtTy::ST|(int).AtTy::HT))
      != 0
      :
      .winty[!`playerno&1] = .fgt.WinTy::Throw;
    else:
      .winty[!`playerno&1] = .fgt.WinTy::N;
    }
  }
  public bool attrCheck(&.Hitdef hit=, int cid, |.StTy styp)
  {
    if(.cgi[`playerno].unhittable > 0) ret false;
    if(hit.chainid >= 0 && `stVal.hb.hitid != hit.chainid) ret false;
    if(#`stVal.hb.by > 0 && `stVal.hb.by[-1].id == cid){
      if(hit.nochainid1 >= 0 && `stVal.hb.hitid == hit.nochainid1) ret false;
      if(hit.nochainid2 >= 0 && `stVal.hb.hitid == hit.nochainid2) ret false;
    }
    if(hit.reversal_attr > 0){
      ret
        `atktmp != 0 && `stVal.hit.attr > 0
        && (`stVal.hit.attr & hit.reversal_attr & 63) != 0
        && (`stVal.hit.attr & hit.reversal_attr & !63) != 0;
    }
    if(hit.attr <= 0) ret false;
    if((hit.hitflag & (int)`stVal.typ) == 0) ret false;
    if((hit.hitflag & (int).StTy::N) == 0 && `hittmp >= 2) ret false;
    if((hit.hitflag & (int).MovTy::I) != 0 && `hittmp > 0) ret false;
    if((hit.hitflag & (int).MovTy::H) != 0 && `hittmp <= 0) ret false;
    if(hit.chainid < 0){
      if(
        `stVal.hb.hitt1 != 0 && (
          (`stVal.hb.hitf1 & (
              styp == .StTy::N ? hit.attr & 63 : (int)styp)) == 0
          || (`stVal.hb.hitf1 & hit.attr & !63) == 0)) ret false;
      if(
        `stVal.hb.hitt2 != 0 && (
          (`stVal.hb.hitf2 & (
              styp == .StTy::N ? hit.attr & 63 : (int)styp)) == 0
          || (`stVal.hb.hitf2 & hit.attr & !63) == 0)) ret false;
    }
    ret true;
  }
  public bool hittable(
    &.Hitdef hit=, `self c=, |.StTy styp, ~$bool(&.Hitdef=) countercheck)
  {
    if(!`attrCheck(hit=, c.id, styp)) ret false;
    if(
      `atktmp != 0 && (
        (`stVal.hit.attr > 0 && `stVal.typ != .StTy::L)
        || `stVal.hit.reversal_attr > 0))
    {
      branch{
      cond `stVal.hit.reversal_attr > 0:
        if(hit.reversal_attr > 0){
          if(countercheck(:`stVal.hit=:)){
            `atktmp = -1;
            ret c.atktmp < 0;
          }
          break, else;
        }
      cond hit.reversal_attr > 0:
        break;
      cond hit.priority < `stVal.hit.priority:
      cond hit.priority == `stVal.hit.priority:
        branch{
        cond `stVal.hit.bothhittype == .PriTy::Dodge:
        cond hit.bothhittype != .PriTy::Hit:
        cond `stVal.hit.bothhittype == .PriTy::Hit:
          if(
            (
              `stVal.hit.p1stateno >= 0 || (
                (
                  `stVal.hit.attr
                  &((int).AtTy::NT|(int).AtTy::ST|(int).AtTy::HT)) != 0
                && hit.hitonce != 0))
            && countercheck(:`stVal.hit=:))
          {
            `atktmp = -1;
            ret c.atktmp < 0 || .m.rand(0, 1) == 1;
          }
          else;
        else:
          break, else;
        }
      else:
        break;
      comm:
        if(countercheck(:`stVal.hit=:)) ret false;
      }
    }
    ret true;
  }
  public bool clsnCheck(`self atk=, bool c1atk, bool c1slf)
  {
    if(#atk.curFrame == 0 || #`curFrame == 0) ret false;
    ^&.act.Rect clsn1 = c1atk ? atk.curFrame~clsn1() : atk.curFrame~clsn2();
    ^&.act.Rect clsn2 = c1slf ? `curFrame~clsn1() : `curFrame~clsn2();
    &.ClsnHantei ch.set(
      #atk.sysfvar[.fCLSNXSCALE], atk.sysfvar[.fCLSNYSCALE],
      atk.sysfvar[.fX] + atk.offsetX(), atk.sysfvar[.fY] + atk.offsetY(),
      (float)atk.facing*atk.sysfvar[.fCLSNXSCALE] > 0.0 ? .pLrSet : .mLrSet,
      #`sysfvar[.fCLSNXSCALE], `sysfvar[.fCLSNYSCALE],
      `sysfvar[.fX] + `offsetX(), `sysfvar[.fY] + `offsetY(),
      (float)`facing*`sysfvar[.fCLSNXSCALE] > 0.0 ? .pLrSet : .mLrSet);
    loop{index i = 0; while; do:
      loop{index j = 0; while; do:
        if(ch.hantei(clsn1[i], clsn2[j])) ret true;
        j++;
      while j < #clsn2:}
      i++;
    while i < #clsn1:}
    ret false;
  }
  public bool hitCheck(`self atk=)
  {
    ret `clsnCheck(atk=, true, atk.stVal.hit.reversal_attr > 0);
  }
  public bool projHitCheck(&.Projectile pr=)
  {
    if(#pr.ani == 0 || #pr.ani~ani.frames == 0 || #`curFrame == 0) ret false;
    ^&.act.Frame frm;
    ^&.act.Rect clsn1 = pr.ani~ani.currentFrame()=>frm$frm~clsn1();
    ^&.act.Rect clsn2 = `curFrame~clsn2();
    &.ClsnHantei ch.set(
      #pr.clsnscalex, pr.clsnscaley, pr.x, pr.y,
      (float)pr.facing*pr.clsnscalex > 0.0 ? .pLrSet : .mLrSet,
      #`sysfvar[.fCLSNXSCALE], `sysfvar[.fCLSNYSCALE],
      `sysfvar[.fX] + `offsetX(), `sysfvar[.fY] + `offsetY(),
      (float)`facing*`sysfvar[.fCLSNXSCALE] > 0.0 ? .pLrSet : .mLrSet);
    loop{index i = 0; while; do:
      loop{index j = 0; while; do:
        if(ch.hantei(clsn1[i], clsn2[j])) ret true;
        j++;
      while j < #clsn2:}
      i++;
    while i < #clsn1:}
    ret false;
  }
  public bool hitProjCheck(&.Projectile pr=)
  {
    if(
      #pr.ani == 0 || #pr.ani~ani.frames == 0 || `stVal.hit.reversal_attr > 0
      || #`curFrame == 0) ret false;
    ^&.act.Frame frm;
    ^&.act.Rect clsn1 = pr.ani~ani.currentFrame()=>frm$frm~clsn2();
    ^&.act.Rect clsn2 = `curFrame~clsn1();
    &.ClsnHantei ch.set(
      #pr.clsnscalex, pr.clsnscaley, pr.x, pr.y,
      (float)pr.facing*pr.clsnscalex > 0.0 ? .pLrSet : .mLrSet,
      #`sysfvar[.fCLSNXSCALE], `sysfvar[.fCLSNYSCALE],
      `sysfvar[.fX] + `offsetX(), `sysfvar[.fY] + `offsetY(),
      (float)`facing*`sysfvar[.fCLSNXSCALE] > 0.0 ? .pLrSet : .mLrSet);
    loop{index i = 0; while; do:
      loop{index j = 0; while; do:
        if(ch.hantei(clsn1[i], clsn2[j])) ret true;
        j++;
      while j < #clsn2:}
      i++;
    while i < #clsn1:}
    ret false;
  }
  public void tickBind()
  {
    if(`sysivar[.iBINDTIME] > 0) branch{
      ^`self c;
    cond `isBound():
      if(#(c = .players.get(`sysivar[.iBINDTOID])) > 0 && !c~isPaused()){
        `setBindTime(`sysivar[.iBINDTIME]-1);
      }
    else:
      if(!`isPaused()) `setBindTime(`sysivar[.iBINDTIME]-1);
    }
  }
  public void tick()
  {
    if(`acttmp > 0 && #`ani > 0) `ani~ani.action();
    `tickBind();
    if(#`cmd == 0) branch{
    cond `keyctrl:
      `cmd.new(#.chars);
      `cmd~buffer.new(1);
      loop{index i = 0; do:
        `cmd[i].buffer = `cmd~buffer;
        `cmd[i].copyList(.chars[`playerno][0]~cmd[i]=);
        `cmd[i].bufReset();
      while ++i < #`cmd:}
    else:
      `cmd = .chars[`playerno][0]~cmd;
    }
    branch{
    cond `stVal.hitdefContact != 0:
      if(`stVal.hit.hitonce != 0 || `trMoveReversed() != 0){
        `stVal.hit.invalidate(`stVal.typ);
      }
      `stVal.hitdefContact = 0;
    cond `stVal.hit.lhit:
      `stVal.hit.attr &= !63;
      `stVal.hit.attr |= (int)`stVal.typ;
      `stVal.hit.lhit = false;
    }
    if(`stVal.mctime < 0){
      `stVal.mctime = 1;
      if(`stVal.mctyp == .MoveContact::Hit){
        `stVal.juggle = 0;
        `sysivar[.iHITCOUNT] += `stVal.hit.numhits;
      }
    }
    if(`ls(.lsGETHIT)){
      `stVal.mov = .MovTy::H;
      if(`sysivar[.iHITPAUSETIME] > 0) `stVal.clearWw();
      `sysivar[.iHITPAUSETIME] = 0;
      if(`ho >= 0 && `stVal.ho[`ho].forceair != 0) `stVal.typ = .StTy::A;
      branch{
        int pn =
          `stVal.hb.p2getp1state && !`stVal.hb.guarded
          ? `stVal.hb.player : `playerno;
      cond `cs1tmp:
        `stVal.prevno = 0;
      cond `stVal.typ == .StTy::L:
        `trChangeState2(5080, pn, -1, 0);
      cond
        `stVal.hb.guarded
        && (`stVal.hb.damage < `sysivar[.iLIFE] || .gs(.gsNOKO))
        :
        switch(`stVal.typ){
        case .StTy::S:
          `trSelfState(150, -1, 0);
        case .StTy::C:
          `trSelfState(152, -1, 0);
        case .StTy::A:
          `trSelfState(154, -1, 0);
        }
      cond `stVal.hb.typ == 3:
        `trChangeState2(5070, pn, -1, 0);
      else:
        if(`stVal.hb.forcestand && `stVal.typ == .StTy::C){
          `stVal.typ = .StTy::S;
        }
        switch(`stVal.typ){
        case .StTy::S:
          `trChangeState2(5000, pn, -1, 0);
        case .StTy::C:
          `trChangeState2(5010, pn, -1, 0);
        case .StTy::A:
          `trChangeState2(5020, pn, -1, 0);
        }
      }
      if(`ho >= 0){
        `changeState1(`stVal.ho[`ho].player, `stVal.ho[`ho].stateno);
      }
    }
    if(!`isPaused()){
      {
        if(`sysivar[.iHITPAUSETIME] > 0){
          if(--`sysivar[.iHITPAUSETIME] > 0) break, break;
          `stVal.clearWw();
        }
        if(
          `stVal.typ == .StTy::L && `sysivar[.iRECOVERTIME] > 0
          && `stVal.playerno == `playerno
          && (
            `cmd~buffer~Bb == 1 || `cmd~buffer~Db == 1
            || `cmd~buffer~Fb == 1 || `cmd~buffer~Ub == 1
            || `cmd~buffer~ab == 1 || `cmd~buffer~bb == 1
            || `cmd~buffer~cb == 1 || `cmd~buffer~xb == 1
            || `cmd~buffer~yb == 1 || `cmd~buffer~zb == 1
            || `cmd~buffer~sb == 1))
        {
          `sysivar[.iRECOVERTIME] -=
            .m.randI(1, (`sysivar[.iRECOVERTIME]+1)/2);
        }
      }
      if(!`cs1tmp) branch{
      cond 
        `helperindex == 0 && (!`isKO() || `stVal.no == 0)
        && `sysivar[.iLIFE] <= 0 && `stVal.mov != .MovTy::H && !.gs(.gsNOKO)
        :
        `stVal.hb.fallf = true;
        `trSelfState(5030, -1, -1);
        `stVal.time = 1;
      cond `stVal.no == 5150 && `stVal.time >= 90 && `isAlive():
        `trSelfState(5120, -1, -1);
      }
    }
    `minus = 11;
    `state_i1(::);
  }
  public void drawAnim()
  {
    if(`helperindex < 0) ret;
    if(.com.clsndraw && #`curFrame > 0){
      float x = `sysfvar[.fX]+`offsetX();
      float y = `sysfvar[.fY]+`offsetY();
      float xs = (float)`facing * `sysfvar[.fCLSNXSCALE];
      float ys = `sysfvar[.fCLSNYSCALE];
      ^&.act.Rect clsn = `curFrame~clsn1();
      if(#clsn > 0 && `atktmp != 0) .drawc1.new[-1].set(clsn, x, y, xs, ys);
      clsn = `curFrame~clsn2();
      if(#clsn > 0) branch{
      cond `stVal.hb.hitt1 != 0 || `stVal.hb.hitt2 != 0:
        if(
          `stVal.hb.hitt1 != 0 && (
            (`stVal.hb.hitf1 & .SCA) == 0 || (`stVal.hb.hitf1 & .ATP) == 0)
          || `stVal.hb.hitt2 != 0 && (
            (`stVal.hb.hitf2 & .SCA) == 0 || (`stVal.hb.hitf2 & .ATP) == 0)){
          .drawc2mtk.new[-1].set(clsn, x, y, xs, ys);
          break, break;
        }
        .drawc2sp.new[-1].set(clsn, x, y, xs, ys);
      else:
        .drawc2.new[-1].set(clsn, x, y, xs, ys);
      }
      if(`ls(.lsPLAYERPUSH)){
        clsn.new(1);
        clsn~l = (int)-`backw;
        clsn~t = (int)-`getHeight();
        clsn~r = (int)`frontw;
        clsn~b = 0;
        .drawwh.new[-1].set(
          clsn, `sysfvar[.fX], `sysfvar[.fY], (float)`facing, 1.0);
      }
    }
    if(#`ani > 0) branch{
      float x = `drawX+`offsetX(), y = `drawY+`offsetY();
      float xs = (float)`facing * `sysfvar[.fXSCALE], ys = `sysfvar[.fYSCALE];
      bool br = `playerno == .superplayer;
      float an;
      branch{
      cond `ls(.lsANGLEDRAW):
        an = `sysfvar[.fANGLE] == 0.0 ? 360.0
        : `facing > 0 ? `sysfvar[.fANGLE] : -`sysfvar[.fANGLE];
      else:
        an = 0.0;
      }
    cond !`ls(.lsINVISIBLE):
      if(`mver0() != 1 && `ls(.lsANGLEDRAW) && !`ls(.lsTRANS)){
        `sysivar[.iSPECIALFLAG] |= .lsTRANS;
        `sysivar[.iALPHAS] = 255;
        `sysivar[.iALPHAD] = 0;
      }
      .addAnimList(
        .anims=, `ani, `sprpriority,
        x - (float)(
          (int)(`stVal.hb.hitshaketime > 0 && (`stVal.time&1) != 0) * `facing),
        y, false, xs, ys, an, `mver0() != 1,
        `sysfvar[.fANGLESCALEX], `sysfvar[.fANGLESCALEY],
        `ls(.lsTRANS) ? `sysivar[.iALPHAS] : -1,
        `sysivar[.iALPHAD], br, `getPalfx(),
        `ls(.lsNOSHADOW) ? 0 : -1, `ls(.lsTRANS) ? `sysivar[.iALPHAS] : 256,
        (float)`sysivar[.iSHADOWOFFSET], `offsetY());
      `aimg.recAndAddAL(
        `ani<>=, `sprpriority, x, y, xs, ys, an, `mver0() != 1,
        `sysfvar[.fANGLESCALEX], `sysfvar[.fANGLESCALEY],
        .com.tickNextFrame() && `acttmp > 0, br, `getPalfx());
    cond .com.tickNextFrame() && `acttmp > 0:
      `aimg.recAfterImg(
        `ani<>=, x, y, xs, ys, an, `mver0() != 1,
        `sysfvar[.fANGLESCALEX], `sysfvar[.fANGLESCALEY], `getPalfx());
    }
    if(.com.tickNextFrame()){
      if(`roundState() == 4) `outTarget(false);
      if(.supertime < 0){
        if((`playerno&1) != (.superplayer&1) && `stVal.mov == .MovTy::H){
          `defencemul *= .superp2defmul;
        }
      }
      `minus = 2;
      `ticOldX = `sysfvar[.fX];
      `ticOldY = `sysfvar[.fY];
    }
  }
  /int roundState()
  {
    ret
      .com.intro > .fight~ro.ctrl_time+1 ? 0
      : .fight~ro.cur == 0 ? 1
      : !.roundEnd() ? 2
      : (
        .com.intro < -(.fight~ro.over_hittime + .fight~ro.over_waittime)
        && (.chars[`playerno]<>~sf(.sfOVER) || .chars[`playerno]<>~isKO())
        ? 4 : 3);
  }
  /bool isKO()
  {
    ret `sf(.sfKO);
  }
  /bool isAlive()
  {
    ret !`isKO();
  }
  /bool isPaused()
  {
    ret `acttmp <= -2;
  }
  /bool isHitPaused()
  {
    ret `sysivar[.iHITPAUSETIME] > 0;
  }
  /bool isActive()
  {
    ret !`isPaused() && !`isHitPaused();
  }
  /bool isBound()
  {
    ret `stVal.hb.byidMatch(`sysivar[.iBINDTOID]);
  }
  /bool isFall()
  {
    ret `stVal.hb.fallf;
  }
  /float getHeight()
  {
    ret (float)`sysivar[.iHEIGHT];
  }
  /float getEdge(float base, bool actually)
  {
    ret
      base + (
        actually && `stMver0() == 1 ? 0.0
        : `stVal.typ == .StTy::A ? 1.0
        : `stVal.typ == .StTy::L ? 2.0
        : 0.0);
  }
  /float defFW()
  {
    ret
      (float)(
        `stVal.typ == .StTy::A
        ? `sysivar[.iAIR_FRONT] : `sysivar[.iGROUND_FRONT]);
  }
  /float defBW()
  {
    ret
      (float)(
        `stVal.typ == .StTy::A
        ? `sysivar[.iAIR_BACK] : `sysivar[.iGROUND_BACK]);
  }
  /float offsetX()
  {
    ret (float)`sysivar[.iDRAW_OFFSETX]*(float)`facing + `offsetx;
  }
  /float offsetY()
  {
    ret (float)`sysivar[.iDRAW_OFFSETY] + `offsety;
  }
  /int palno()
  {
    ret `helperindex == 0 || `mver0() == 1 ? .cgi[`playerno].palno : 1;
  }
  /int mver0()
  {
    ret .cgi[`playerno].mver0;
  }
  /int stMver0()
  {
    ret .cgi[`minus < 0 ? `playerno : `stVal.playerno].mver0;
  }
  /bool landCondition()
  {
    ret
      `stVal.phy == .StTy::A && `sysfvar[.fVY] > 0.0
      && `sysfvar[.fY] >= 0.0 && `stVal.no != 105;
  }
  /bool inGuardState()
  {
    ret
      `stVal.no == 120 || (`stVal.no >= 130 && `stVal.no <= 132)
      || `stVal.no == 140 || (`stVal.no >= 150 && `stVal.no <= 155);
  }
  public void furimuki()
  {
    if(`ctrl && `helperindex == 0){
      if(`trDistX(.players.enemyNear(`=, 0, true))$.v.toF() >= 0.0) break;
      branch{
      cond `stVal.typ == .StTy::S:
        `trChangeAnim(5);
      cond `stVal.typ == .StTy::C:
        `trChangeAnim(6);
      }
      `setFacing(-`facing);
    }
  }
  /bool isHouchied()
  {
    ret `sf(.sfKO_ROUND_MIDDLE);
  }
  public void action()
  {
    if(`minus != 2 || `ls(.lsDESTROY)) ret;
    bool p =
      .super > 0 ? `sysivar[.iSUPERMOVETIME] == 0
      : .pause > 0 && `sysivar[.iPAUSEMOVETIME] == 0;
    if(#`cmd == 0) p = false;
    `acttmp = -(int)p * 2;
    `sysivar[.iSYSFLAG] &= !.sfGUARD;
    if(
      !(`isKO() || `ctrlOver()) && (`ctrl || `stVal.no == 52)
      && `stVal.mov == .MovTy::I && #`cmd > 0
      && (.com.autoguard[`playerno] || `cmd~buffer~B > 0) && (
        (`stVal.typ == .StTy::S && !`ls(.lsNOSTANDGUARD))
        || (`stVal.typ == .StTy::C && !`ls(.lsNOCROUCHGUARD))
        || (`stVal.typ == .StTy::A && !`ls(.lsNOAIRGUARD))))
    {
      `sysivar[.iSYSFLAG] |= .sfGUARD;
    }
    if(!p){
      if(#`palfx > 0) `palfx~step();
      if(`keyctrl && #`cmd > 0) branch{
        branch{
        cond `stVal.typ == .StTy::A:
          if(`cmd~buffer~U < 0) `sysivar[.iSYSFLAG] |= .sfAIRJUMP;
        else:
          `sysivar[.iAIRJUMP_CNT] = 0;
          `sysivar[.iSYSFLAG] &= !.sfAIRJUMP;
        }
      cond `canCtrl() && (`key >= 0 || `helperindex == 0):
        branch{
        cond !.roundEnd() && `stVal.typ == .StTy::S && `cmd~buffer~U > 0:
          if(`stVal.no != 40) `trChangeState(40, -1, -1);
        cond
          `stVal.typ == .StTy::A && `sf(.sfAIRJUMP)
          && `sysfvar[.fY] <= (float)`sysivar[.iAIRJUMP_HEIGHT]
          && `sysivar[.iAIRJUMP_CNT] < `sysivar[.iAIRJUMP_NUM]
          && `cmd~buffer~U > 0
          :
          if(`stVal.no != 45){
            `sysivar[.iAIRJUMP_CNT]++;
            `sysivar[.iSYSFLAG] &= !.sfAIRJUMP;
            `trChangeState(45, -1, -1);
          }
        else:
          branch{
          cond `stVal.typ == .StTy::S && `cmd~buffer~D > 0:
            if(`stVal.no != 10) `trChangeState(10, -1, -1);
          cond `stVal.typ == .StTy::C && `cmd~buffer~D < 0:
            if(`stVal.no != 12) `trChangeState(12, -1, -1);
          cond
            !`ls(.lsNOWALK) && `stVal.typ == .StTy::S && (
              `cmd~buffer~F > 0
              || (!(`inguarddist && `sf(.sfGUARD)) && `cmd~buffer~B > 0))
            :
            if(`stVal.no != 20) `trChangeState(20, -1, -1);
          cond `stVal.no == 20 && `cmd~buffer~F < 0 && `cmd~buffer~B < 0:
            `trChangeState(0, -1, -1);
          }
          if(
            `inguarddist && `sf(.sfGUARD) && `cmd~buffer~B > 0
            && !`inGuardState())
          {
            `trChangeState(120, -1, -1);
          }
        }
      cond `ctrl:
        switch(`stVal.no){
        case 11:
          `trChangeState(12, -1, 1);
        case 20:
          `trChangeState(0, -1, 1);
        }
      }
      if(!`isHitPaused()){
        if(!`ls(.lsNOAUTOTURN) && `stVal.no == 52){
          `furimuki();
        }
        if(!.roundEnd()){
          if(!`isKO() && `sysivar[.iLIFE] > 0){
            `sysivar[.iSYSFLAG] &= !(.sfOVER | .sfKO_ROUND_MIDDLE);
          }
          if(`stVal.no == 5150 || `sf(.sfOVER)){
            `sysivar[.iSYSFLAG] |= .sfKO_ROUND_MIDDLE;
          }
        }
        if(`stVal.no == 5150) `sysivar[.iSYSFLAG] |= .sfOVER;
        `sysivar[.iSPECIALFLAG] =
          `player ? (
            (!`isKO() || !`sf(.sfOVER))
            ? (
              .lsSCREENBOUND | .lsMOVECAMERAX | .lsMOVECAMERAY
              | (`roundState() > 0 ? .lsPLAYERPUSH : 0))
            : (
              `isHouchied()
              ? 0 : .lsSCREENBOUND | .lsMOVECAMERAX | .lsMOVECAMERAY))
          : 0;
        `sysfvar[.fANGLESCALEX] = `sysfvar[.fANGLESCALEY] = 1.0;
        `offsetx = `offsety = 0.0;
        `attackdist = (float)`sysivar[.iATTACK_DIST];
        if(`stVal.hb.hitt1 > 0) `stVal.hb.hitt1--;
        if(`stVal.hb.hitt2 > 0) `stVal.hb.hitt2--;
        loop{index i = 0; while; do:
          if(`stVal.ho[i].time > 0) `stVal.ho[i].time--;
          i++;
        while i < #`stVal.ho:}
        branch{
        cond .super > 0:
          if(`sysivar[.iSUPERMOVETIME] > 0) `sysivar[.iSUPERMOVETIME]--;
        cond .pause > 0 && `sysivar[.iPAUSEMOVETIME] > 0:
          `sysivar[.iPAUSEMOVETIME]--;
        }
      }
      `sysivar[.iSPECIALFLAG] &= !.lsNOAUTOTURN;
      if(`mver0() == 1){
        `sysivar[.iSPECIALFLAG] &= !(.lasMask | .lsANGLEDRAW);
        `sysfvar[.fANGLESCALEX] = `sysfvar[.fANGLESCALEY] = 1.0;
        `offsetx = `offsety = 0.0;
      }
      `minus = -3;
      if(`stVal.playerno == `playerno && `player) `state_3(::);
      `minus = -2;
      if(`player) `state_2(::);
      `minus = -1;
      if(`keyctrl && `stVal.playerno == `playerno) `state_1(::);
      `changeState2();
      `minus = 0;
      `state(::);
      if(!`isHitPaused()){
        if(`stVal.no == 5110 && `sysivar[.iRECOVERTIME] <= 0 && `isAlive()){
          `trChangeState(5120, -1, -1);
        }
        loop{while; do:
          `trChangeState(
            (int)(`stVal.typ == .StTy::C)*11
            + (int)(`stVal.typ == .StTy::A)*51, -1, -1);
        while
          `stVal.no == 140 && `stVal.time >= (
            #`ani > 0 && #`ani~ani.frames > 0 ? `ani~ani.totaltime : 0)
          :
        }
        loop{continue; do:
          `trChangeState(52, -1, -1);
        continue:
          `posUpdate();
        while `landCondition():}
        `stVal.time++;
        if(`stVal.mctime > 0) `stVal.mctime++;
        `setFacing(`p1facing);
        `p1facing = 0;
        branch{
        cond #`ani > 0:
          `curFrame = `ani~ani.currentFrame();
        else:
          `curFrame.new(0);
        }
      }
      if(`stVal.hb.damage != 0){
        if(`stVal.mov == .MovTy::H){
          `addLife(-(double)`stVal.hb.damage, true, true);
        }
        `stVal.hb.damage = 0;
      }
      if(`helperindex == 0 && .cgi[`playerno].pctime >= 0){
        .cgi[`playerno].pctime++;
      }
    }
    `xScreenBound();
    if(!p) `targets:<-[void(t=){
      ^`self c = .players.get(t);
      if(#c > 0 && c~sysivar[.iBINDTOID] == `id) c~bind();
    }];
    `minus = 1;
    `acttmp += (int)`isActive() - (int)`isHitPaused();
    if(!`isHitPaused()){
      if(!`ls(.lsFRONTWCHANGE)) `frontw = `defFW();
      if(!`ls(.lsBACKWCHANGE)) `backw = `defBW();
      if(!`ls(.lsFEDGECHANGE)) `fedge = 0.0;
      if(!`ls(.lsBEDGECHANGE)) `bedge = 0.0;
    }
  }
  public void posUpdate()
  {
    bool nobindx = `sysivar[.iBINDTIME] == 0 || .m.isnan(`sysfvar[.fBINDPOSX]);
    bool nobindy = `sysivar[.iBINDTIME] == 0 || .m.isnan(`sysfvar[.fBINDPOSY]);
    if(nobindx) `ticOldX = `drawX = `sysfvar[.fX];
    if(nobindy) `ticOldY = `drawY = `sysfvar[.fY];
    branch{
    cond `ls(.lsPOSFREEZEX):
      if(nobindx) `setPosX(`ticOldX + `veloff);
    else:
      if(nobindx) `setPosX(`ticOldX + `sysfvar[.fVX]*(float)`facing + `veloff);
      switch(`stVal.phy){
      case .StTy::S:
        `sysfvar[.fVX] *= `sysfvar[.fSTAND_FRICTION];
        if(#`sysfvar[.fVX] < 1.0) `sysfvar[.fVX] = 0.0;
      case .StTy::C:
        `sysfvar[.fVX] *= `sysfvar[.fCROUCH_FRICTION];
      }
    }
    `veloff *= 0.7;
    if(#`veloff < 1.0) `veloff = 0.0;
    if(!`ls(.lsPOSFREEZEY)){
      if(nobindy) `setPosY(`ticOldY + `sysfvar[.fVY]);
      if(`stVal.phy == .StTy::A) `gravity();
    }
  }
  public void gravity()
  {
    `sysfvar[.fVY] += `sysfvar[.fYACCEL];
  }
  public void bind()
  {
    if(`sysivar[.iBINDTIME] == 0) ret;
    ^`self c = .players.get(`sysivar[.iBINDTOID]);
    branch{
    cond #c > 0:
      if(c~hasTarget(`id)){
        if(c~ls(.lsDESTROY)){
          `trSelfState(5050, -1, -1);
          break, break, else;
        }
        if(!.m.isnan(`sysfvar[.fBINDPOSX])){
          `setXV((float)(`facing*c~facing)*c~sysfvar[.fVX]);
        }
        if(!.m.isnan(`sysfvar[.fBINDPOSY])) `setYV(c~sysfvar[.fVY]);
      }
    else:
      `setBindTime(0);
      ret;
    }
    if(!.m.isnan(`sysfvar[.fBINDPOSX])){
      float f =
        (float)(
          #`sysivar[.iBINDFACING] == 2 ? `sysivar[.iBINDFACING]/2 : c~facing);
      `setX(c~sysfvar[.fX] + f*`sysfvar[.fBINDPOSX]);
      `drawX += c~drawX - c~sysfvar[.fX];
      `ticOldX += c~ticOldX - c~sysfvar[.fX];
      `pushed |= c~pushed;
      `stVal.hb.xoff = 0.0;
    }
    if(!.m.isnan(`sysfvar[.fBINDPOSY])){
      `setY(c~sysfvar[.fY] + `sysfvar[.fBINDPOSY]);
      `drawY += c~drawY - c~sysfvar[.fY];
      `ticOldY += c~ticOldY - c~sysfvar[.fY];
      `stVal.hb.yoff = 0.0;
    }
    if(#`sysivar[.iBINDFACING] == 1) branch{
    cond `sysivar[.iBINDFACING] > 0: `setFacing(c~facing);
    cond `sysivar[.iBINDFACING] < 0: `setFacing(-c~facing);
    }
  }
  public void xScreenBound()
  {
    float x = `sysfvar[.fX];
    if(`ls(.lsSCREENBOUND)){
      float min, max;
      branch{
      cond `facing > 0:
        min = .com.xmin + `getEdge(`bedge, true);
        max = .com.xmax - `getEdge(`fedge, true);
      else:
        min = .com.xmin + `getEdge(`fedge, true);
        max = .com.xmax - `getEdge(`bedge, true);
      }
      .m.limRange!float?(x=, min, max);
    }
    .m.limRange!float?(x=, (float).stg~leftbound, (float).stg~rightbound);
    `setPosX(x);
  }
  public void update(
    float cvmin=, float cvmax=,
    float highest=, float lowest=, float leftest=, float rightest=)
  {
    if(.com.tickFrame()){
      if(`ls(.lsDESTROY)){
        `destroySelf();
        ret;
      }
      if(!`isPaused() && !`isBound()) `bind();
      if(`acttmp > 0){
        if(#`ani > 0) `ani~ani.updateSprite();
        if(`stVal.mov == .MovTy::H){
          if(`stVal.hb.xoff != 0.0){
            `setPosX(`sysfvar[.fX] + `stVal.hb.xoff);
            `stVal.hb.xoff = 0.0;
          }
          if(`stVal.hb.yoff != 0.0){
            `setPosY(`sysfvar[.fY] + `stVal.hb.yoff);
            `stVal.hb.yoff = 0.0;
          }
        }
      }
      if(`stVal.mov == .MovTy::H){
        if(.super <= 0 && .pause <= 0){
          `sysivar[.iSUPERMOVETIME] = `sysivar[.iPAUSEMOVETIME] = 0;
        }
        `hittmp = (int)`isFall() + 1;
        if(
          `acttmp > 0
          && (`stVal.no == 5100 || `stVal.no == 5070) && `stVal.time == 1)
        {
          `defencemul *= `sysfvar[.fFALL_DEFENCE_MUL];
          `stVal.hb.fallcount++;
        }
      }
      if(
        (`acttmp > 0 && `stVal.mov != .MovTy::H) || (
          `roundState() == 2 && `isKO() && `sf(.sfOVER)))
      {
        `outTarget(true);
      }
      `atktmp =
        (`stVal.mov != .MovTy::I || `stVal.hit.reversal_attr > 0)
        && !`isHitPaused() ? 1 : 0;
      `ho = -1;
      if(`acttmp > 0){
        if(`inGuardState()) `sysivar[.iSYSFLAG] |= .sfGUARD;
        branch{
        cond `stVal.mov == .MovTy::H:
          if(`stVal.hb.guarded) `getcombo = 0;
          if(`stVal.hb.hitshaketime > 0) `stVal.hb.hitshaketime--;
          if(`stVal.hb.hitshaketime <= 0 && `stVal.hb.hittime >= 0){
            `stVal.hb.hittime--;
          }
          if(`isFall()) `stVal.fallTime++;
        else:
          if(`hittmp > 0) `hittmp = 0;
          `defencemul = (float)`sysivar[.iDEFENCE] / 100.0;
          `stVal.hb.hittime = -1;
          `stVal.hb.hitshaketime = 0;
          `stVal.hb.fallf = false;
          `stVal.hb.fallcount = 0;
          `stVal.hb.hitid = -1;
          `getcombo = 0;
        }
        if(
          (`stVal.mov == .MovTy::H || `stVal.no == 52) && `sysfvar[.fY] == 0.0
          && #(`sysfvar[.fX]-`ticOldX) >= 1.0 && `stVal.time % 3 == 0)
        {
          `makeDust(0.0, 0.0);
        }
      }
    }
    if(.com.tickNextFrame()) `pushed = false;
    if(`acttmp > 0){
      float sp = `pushed ? 0.0 : .com.tickInterpola();
      if(!`ls(.lsPOSFREEZEX)){
        `drawX = `sysfvar[.fX] - (`sysfvar[.fX] - `ticOldX) * (1.0 - sp);
      }
      if(!`ls(.lsPOSFREEZEY)){
        `drawY = `sysfvar[.fY] - (`sysfvar[.fY] - `ticOldY) * (1.0 - sp);
      }
    }
    if(`ls(.lsSCREENBOUND)){
      float min, max;
      branch{
      cond `facing > 0:
        min = .com.xmin + `getEdge(`bedge, true);
        max = .com.xmax - `getEdge(`fedge, true);
      else:
        min = .com.xmin + `getEdge(`fedge, true);
        max = .com.xmax - `getEdge(`bedge, true);
      }
      .m.limRange!float?(`drawX=, min, max);
    }
    if(`ls(.lsMOVECAMERAX)){
      leftest = .m.max!float?(.com.xmin)<, .m.min!float?(
        `drawX-`getEdge(`facing > 0 ? `bedge : `fedge, true), leftest);
      rightest = .m.min!float?(.com.xmax)<, .m.max!float?(
        `drawX+`getEdge(`facing > 0 ? `fedge : `bedge, true), rightest);
      if(
        `acttmp > 0 && !`ls(.lsPOSFREEZEX)
        && (`sysivar[.iBINDTIME] == 0 || .m.isnan(`sysfvar[.fBINDPOSX])))
      {
        cvmin = .m.min!float?(cvmin, `sysfvar[.fVX]*(float)`facing);
        cvmax = .m.max!float?(cvmax, `sysfvar[.fVX]*(float)`facing);
      }
    }
    if(`ls(.lsMOVECAMERAY)){
      highest = .m.min!float?(`drawY, highest);
      lowest = .m.min!float?(0.0)<, .m.max!float?(`drawY, lowest);
    }
  }
  public void posReset()
  {
    `facing = (`playerno&1) == 0 ? .stg~p1.facing : .stg~p2.facing;
    `setX(
      (float)(
        ((`playerno&1) == 0 ? .stg~p1.startx : .stg~p2.startx)
        - .com.cam.stg.startx)
      * .stg~localscl + (float)(`playerno*-`facing / 2) * .com.P1P3Dist);
    `setY(0.0);
    `setXV(0.0);
    `setYV(0.0);
  }
  void nikou<if_t, ff_t>(&.Var rtn=, &.Var var1, &.Var var2)
  {
    branch{
    cond
      ((int)var1.typ - (int).VarTy::Float)
      * ((int)var2.typ - (int).VarTy::Float) == 0
      :
      ff_t(rtn=, var1.toF(), var2.toF());
    else:
      if_t(rtn=, var1.toI(), var2.toI());
    }
  }
  public void setLife(int l)
  {
    `sysivar[.iLIFE] = .m.max!int?(0)<, .m.min!int?(`sysivar[.iLIFEMAX])<, l;
    if(`sysivar[.iLIFE] == 0) branch{
    cond `player:
      if(!`isKO()) `setEnemyWinty();
    else:
      `sysivar[.iLIFE] = 1;
    }
  }
  public int getDamage(double damage, bool kill, bool absolute, float atkmul)
  {
    if(damage == 0.0 || (!absolute && atkmul == 0.0)) ret 0;
    type _t = double;
    ret
      (int).m.min!_t?((*_t)(.m.max!int?(0, `sysivar[.iLIFE]-(int)!kill)))<,
      .m.max!_t?((*_t)(`sysivar[.iLIFE]-`sysivar[.iLIFEMAX]))<,
      .m.ceil(damage*(absolute ? 1.0 : atkmul/`defencemul*`defencemult));
  }
  public void addLife(double l, bool kill, bool absolute)
  {
    if(l == 0.0 || `roundState() == 3) ret;
    `setLife(
      `sysivar[.iLIFE]
      + (int).m.max!double?(
        (double)(-`sysivar[.iLIFE] + (int)(!kill && `sysivar[.iLIFE] > 0)))<,
      .m.min!double?((double)(`sysivar[.iLIFEMAX]-`sysivar[.iLIFE]))<,
      .m.floor(l / (absolute ? 1.0 : `defencemul)));
  }
  public void setPower(int p)
  {
    if(.roundEnd()) ret;
    `sysivar[.iPOWER] = .m.max!int?(0)<, .m.min!int?(`sysivar[.iPOWERMAX])<, p;
  }
  public int getSharePower()
  {
    ret
      .chars[`playerno & (.com.powerShare[`playerno&1]?1:-1)]<>
        ~sysivar[.iPOWER];
  }
  public void addPower(int p)
  {
    .chars[`playerno&(.com.powerShare[`playerno&1]?1:-1)]<>
      ~setPower(`getSharePower() + p);
  }
  public void setFacing(int f)
  {
    if(f == 0) ret;
    if((`facing < 0) != (f < 0)){
      `facing *= -1;
      `sysfvar[.fVX] *= -1.0;
      `stVal.hb.xvel *= -1.0;
    }
  }
  void setFWidth(float f)
  {
    `frontw = `defFW() + f;
    `sysivar[.iSPECIALFLAG] |= .lsFRONTWCHANGE;
  }
  void setBWidth(float b)
  {
    `backw = `defBW() + b;
    `sysivar[.iSPECIALFLAG] |= .lsBACKWCHANGE;
  }
  void setFEdge(float f)
  {
    `fedge = f;
    `sysivar[.iSPECIALFLAG] |= .lsFEDGECHANGE;
  }
  void setBEdge(float b)
  {
    `bedge = b;
    `sysivar[.iSPECIALFLAG] |= .lsBEDGECHANGE;
  }
  void setPauseTime(int pausetime, int movetime)
  {
    if(
      !pausetime < .pausetime || `playerno != `stVal.playerno
      || .pauseplayer == `playerno)
    {
      .pausetime = !pausetime;
      .pauseplayer = `playerno;
      .m.limMin!int?(.pauseendcmdbuftime=, 0);
      if(.pauseendcmdbuftime > pausetime) .pauseendcmdbuftime = 0;
    }
    `sysivar[.iPAUSEMOVETIME] = .m.max!int?(0, movetime);
    branch{
    cond `sysivar[.iPAUSEMOVETIME] > pausetime:
      `sysivar[.iPAUSEMOVETIME] = 0;
    cond .pause > 0 && `sysivar[.iPAUSEMOVETIME] > 0:
      `sysivar[.iPAUSEMOVETIME]--;
    }
  }
  void setSuperPauseTime(int pausetime, int movetime, bool unhittable)
  {
    if(
      !pausetime < .supertime || `playerno != `stVal.playerno
      || .superplayer == `playerno)
    {
      .supertime = !pausetime;
      .superplayer = `playerno;
      .m.limMin!int?(.superendcmdbuftime=, 0);
      if(.superendcmdbuftime > pausetime) .superendcmdbuftime = 0;
    }
    `sysivar[.iSUPERMOVETIME] = .m.max!int?(0, movetime);
    branch{
    cond `sysivar[.iSUPERMOVETIME] > pausetime:
      `sysivar[.iSUPERMOVETIME] = 0;
    cond .super > 0 && `sysivar[.iSUPERMOVETIME] > 0:
      `sysivar[.iSUPERMOVETIME]--;
    }
    if(unhittable){
      .cgi[`playerno].unhittable = pausetime + (int)(pausetime > 0);
    }
  }
  void setHitdefDefault(&.Hitdef h=, bool proj)
  {
    if(!proj) `targetsOfHit.new(0);
    if((h.attr & !63) == 0) h.attr = 0;
    if(
      h.hitonce < 0
      || (h.attr&((int).AtTy::NT|(int).AtTy::ST|(int).AtTy::HT)) != 0)
    {
      h.hitonce = 1;
    }
    if(.m.isnan(h.ground_velocityx)) h.ground_velocityx = 0.0;
    if(.m.isnan(h.ground_velocityy)) h.ground_velocityy = 0.0;
    if(.m.isnan(h.air_velocityx)) h.air_velocityx = 0.0;
    if(.m.isnan(h.air_velocityy)) h.air_velocityy = 0.0;
    if(.m.isnan(h.guard_velocity)) h.guard_velocity = h.ground_velocityx;
    if(.m.isnan(h.airguard_velocityx)){
      h.airguard_velocityx = h.air_velocityx*1.5;
    }
    if(.m.isnan(h.airguard_velocityy)){
      h.airguard_velocityy = h.air_velocityy*0.5;
    }
    if(.m.isnan(h.down_velocityx)) h.down_velocityx = h.air_velocityx;
    if(.m.isnan(h.down_velocityy)) h.down_velocityy = h.air_velocityy;
    if(h.air_fall == .com.IERR) h.air_fall = h.ground_fall;
    if(h.fall.animtype == .AnimTy::Unknown) branch{
    cond h.air_animtype != .AnimTy::Unknown:
      h.fall.animtype = h.air_animtype;
    cond (int)h.animtype < 3:
      h.fall.animtype = .AnimTy::Back;
    else:
      h.fall.animtype = h.animtype;
    }
    if(h.air_animtype == .AnimTy::Unknown) h.air_animtype = h.animtype;
    if(h.air_type == .ReactTy::Unknown){
      h.air_type = h.ground_type;
      if(h.air_type == .ReactTy::Trip) h.air_type = .ReactTy::High;
    }
    if(h.forcestand == .com.IERR){
      h.forcestand = (int)(h.ground_velocityy != 0.0);
    }
    if(.m.isnan(h.ground_cornerpush_veloff)){
      h.ground_cornerpush_veloff =
        (h.attr & (int).StTy::A) != 0 ? 0.0 : h.guard_velocity*1.3;
    }
    if(.m.isnan(h.air_cornerpush_veloff)){
      h.air_cornerpush_veloff = h.ground_cornerpush_veloff;
    }
    if(.m.isnan(h.down_cornerpush_veloff)){
      h.down_cornerpush_veloff = h.ground_cornerpush_veloff;
    }
    if(.m.isnan(h.guard_cornerpush_veloff)){
      h.guard_cornerpush_veloff = h.ground_cornerpush_veloff;
    }
    if(.m.isnan(h.airguard_cornerpush_veloff)){
      h.airguard_cornerpush_veloff = h.ground_cornerpush_veloff;
    }
    if(h.hitgetpower == .com.IERR){
      h.hitgetpower = (int)(.cfg.Attack_LifeToPowerMul*(float)(h.hitdamage));
    }
    if(h.guardgetpower == .com.IERR){
      h.guardgetpower =
        (int)(.cfg.Attack_LifeToPowerMul*(float)(h.hitdamage)*0.5);
    }
    if(h.hitgivepower == .com.IERR){
      h.hitgivepower = (int)(.cfg.GetHit_LifeToPowerMul*(float)(h.hitdamage));
    }
    if(h.guardgivepower == .com.IERR){
      h.guardgivepower =
        (int)(.cfg.GetHit_LifeToPowerMul*(float)(h.hitdamage)*0.5);
    }
    if(!.m.isnan(h.snapx)) h.maxdistx = h.mindistx = h.snapx;
    if(!.m.isnan(h.snapy)) h.maxdisty = h.mindisty = h.snapy;
  }
  void playSound(
    bool f, bool lw, bool lp, int g, int s, int ch,
    int vo, float p, float fr, ^float x)
  {
    if(g < 0) ret;
    ^&.snd.Wave w;
    branch{
    cond f:
      if(#.fight~fsn == 0) break;
      w = .fight~fsn~getSound(g, s);
    else:
      if(#.cgi[`playerno].sn == 0) break;
      w = .cgi[`playerno].sn~getSound(g, s);
    }
    if(#w == 0) ret;
    ^&.snd.Sound sou = `newChannel(ch, lw);
    if(#sou == 0) ret;
    sou~sound = w;
    sou~chrx = x;
    branch{
      int vol = .m.max!int?(-25600, .m.min!int?(25600, vo));
    cond `mver0() == 1:
      sou~setVol(!f ? `sysivar[.iVOLUME] * vol / 100 : 256);
    else:
      sou~setVol(vol + (!f ? `sysivar[.iVOLUME] : 256));
    }
    sou~loop_ = lp;
    sou~lowpriority = lw;
    sou~setPan(p * (float)`facing);
    sou~freqmul = fr;
    sou~fidx = 0.0;
  }
  public bool ctrlOver()
  {
    ret
     .com.time == 0
     || .com.intro < -(.fight~ro.over_hittime + .fight~ro.over_waittime);
  }
  public bool canCtrl()
  {
    ret `ctrl && !`ctrlOver();
  }
  public void setCtrl(bool c)
  {
    `ctrl = c;
  }
  public void destroySelf()
  {:<-
    if(`helperindex <= 0) ret;
    `outTarget(true);
    `getcombo = 0;
    loop{
      index i = 0;
      ^`self c;
      while;
    do:
      c = .players.get(`targets[i]);
      if(#c > 0){
        c~byBindClear();
        c~stVal.hb.dropByid(`id);
      }
      i++;
    while i < #`targets:}
    if(`parentindex >= 0) loop{index i = 0; while; do:
      if(.chars[`playerno][`parentindex]~children[i] == `helperindex){
        .chars[`playerno][`parentindex]~children[i] = -1;
        break, break;
      }
      i++;
    while i < #.chars[`playerno][`parentindex]~children:}
    `children:<-[void(c=){
      if(c >= 0){
        .chars[`playerno][c]~parentindex *= -1;
        c = -1;
      }
    }];
    .players.destroy(`id);
    `helperindex = -1;
    `sysivar[.iSPECIALFLAG] |= .lsDESTROY;
  }
  public void setPosX(float x)
  {
    if(`sysfvar[.fX] != x){
      `sysfvar[.fX] = x;
      `enemynClear();
      if(`player) loop{index i = !`playerno & 1; while; do:
        .chars[i]:<-[void(c=){c~enemynClear();}];
        i += 2;
      while i < #.chars:}
    }
  }
  public void setPosY(float y)
  {
    `sysfvar[.fY] = y;
  }
  public void setX(float x)
  {
    `setPosX(`ticOldX = `drawX = x);
  }
  public void setY(float y)
  {
    `setPosY(`ticOldY = `drawY = y);
  }
  public void setXV(float xv)
  {
    `sysfvar[.fVX] = xv;
  }
  public void setYV(float yv)
  {
    `sysfvar[.fVY] = yv;
  }
  public void setAngle(float a)
  {
    `sysfvar[.fANGLE] = a;
  }
  public void setPos<_t>(_t o=, int pt, float x, float y, int facing)
  {
    branch{
    cond facing < 0:
      o.facing = -1;
    else:
      o.facing = 1;
    }
    switch(pt){
    case 0://p1
      if(!.m.isnan(x)) o.setX(`sysfvar[.fX] + (float)`facing*x);
      if(!.m.isnan(y)) o.setY(`sysfvar[.fY] + y);
      o.facing *= `facing;
    case 1://p2
      {
        ^`self c = .players.enemyNear(`=, 0, true);
        if(#c == 0) break;
        if(!.m.isnan(x)) o.setX(c~sysfvar[.fX] + (float)c~facing*x);
        if(!.m.isnan(y)) o.setY(c~sysfvar[.fY] + y);
        o.facing *= c~facing;
      }
    case 2, 3://front, back
      if(!.m.isnan(x)) branch{
      cond (`facing > 0 && pt == 2) || (`facing < 0 && pt == 3):
        o.setX(
          .com.cam.screenX
          + (.com.CharGameRight - x*(pt == 2 ? -1.0 : 1.0)) / .com.cam.scale);
      else:
        o.setX(
          .com.cam.screenX
          + (.com.CharGameLeft + x*(pt == 2 ? -1.0 : 1.0)) / .com.cam.scale);
      }
      if(!.m.isnan(y)) o.setY(.com.cam.screenY + y / .com.cam.scale);
      o.facing *= `facing;
    case 4://left
      if(!.m.isnan(x)){
        o.setX(.com.cam.screenX + (.com.CharGameLeft + x) / .com.cam.scale);
      }
      if(!.m.isnan(y)) o.setY(.com.cam.screenY + y / .com.cam.scale);
    case 5://right
      if(!.m.isnan(x)){
        o.setX(.com.cam.screenX + (.com.CharGameRight + x) / .com.cam.scale);
      }
      if(!.m.isnan(y)) o.setY(.com.cam.screenY + y / .com.cam.scale);
    case 6:
      if(!.m.isnan(x)) o.setX(x);
      if(!.m.isnan(y)) o.setY(y);
    }
  }
  public void setAlpha(int trans, int salpha=, int dalpha=)
  {
    switch(trans){
    case 0://default
      salpha = -1;
      dalpha = .com.IERR;
    case 1://none
      salpha = 255;
      dalpha = 0;
    case 2://add
      branch{
      cond salpha != .com.IERR:
        salpha = .m.max!int?(0)<, .m.min!int?(255)<, salpha;
        if(salpha == 1) salpha = 0;
      else:
        salpha = 255;
      }
      dalpha = 255;
    case 3://addalpha
      if(salpha != .com.IERR){
        salpha = .m.max!int?(0)<, .m.min!int?(255)<, salpha;
      }
      if(dalpha != .com.IERR){
        dalpha = .m.max!int?(0)<, .m.min!int?(255)<, dalpha;
      }
      if(salpha == 1 && dalpha == 255) salpha = 0;
    case 4://add1
      branch{
      cond salpha != .com.IERR:
        salpha = .m.max!int?(0)<, .m.min!int?(255)<, salpha;
      else:
        salpha = 255;
      }
      branch{
      cond dalpha != .com.IERR:
        dalpha = !.m.max!int?(0)<, .m.min!int?(255)<, dalpha;
      else:
        dalpha = !255;
      }
    case 5://sub
      salpha = 1;
      dalpha = 255;
    }
  }
  public void setBindTime(int time)
  {
    `sysivar[.iBINDTIME] = time;
    if(time == 0) `sysivar[.iBINDTOID] = -1;
  }
  public void setBindToId(`self to=)
  {
    `sysivar[.iBINDTOID] = to.id;
    if(to.sysivar[.iBINDTOID] == `id) to.setBindTime(0);
    `sysivar[.iBINDFACING] = to.facing*2;
  }
  public void makeDust(float x, float y)
  {
    index i;
    ^&.Explod e = `newExplod(i=);
    if(#e==0)ret;
    e~ani = .fight~getAction(120);
    e~ontop = 0;
    e~sprpriority = .consts.int_t::MAX;
    e~ownpal = 1;
    e~offsetx = x;
    e~offsety = y;
    e~setPos(`=);
    `insertExplod(i);
  }
  public void trPlayerID(int id)
  {
    .c = .players.get(id);
  }
  public void trEnemy(int n)
  {
    if(n < 0 || n >= `trNumEnemy()){
      .c.new(0);
      ret;
    }
    .c = .chars[n*2 + (!`playerno&1)]<>;
  }
  public void trEnemyNear(int n)
  {
    .c = .players.enemyNear(`=, n, false);
  }
  public void trRoot()
  {
    if(`helperindex == 0){
      .c.new(0);
      ret;
    }
    .c = .chars[`playerno][0];
  }
  public void trParent()
  {
    branch{
    cond `parentindex == .com.IERR:
      .c.new(0);
    else:
      .c = .chars[`playerno][#`parentindex];
    }
  }
  public void trPartner(int n)
  {
    int no = .m.max!int?(0, n);
    if(no > #.chars / 2 - 2){
      .c.new(0);
      ret;
    }
    int par;
    branch{
    cond no == `playerno >> 1:
      par = `playerno + 2;
    else:
      par = (`playerno & 1) + (no << 1) + (int)(no > `playerno >> 1)*2;
    }
    .c = #.chars[par] > 0 ? .chars[par][0] : .consts.null!`self?();
  }
  public void trHelper(int id)
  {
    loop{index i = 1; while; do:
      if(
        !.chars[`playerno][i]~ls(.lsDESTROY)
        && (id <= 0 || id == .chars[`playerno][i]~helperid))
      {
        .c = .chars[`playerno][i];
        ret;
      }
      i++;
    while i < #.chars[`playerno]:}
    .c = .consts.null!`self?();
  }
  public void trTarget(int id)
  {
    loop{index i = 0; while; do:
      .c = .players.get(`targets[i]);
      if(#.c > 0 && (id < 0 || .c~stVal.hb.hitid == id)) ret;
      i++;
    while i < #`targets:}
    .c = .consts.null!`self?();
  }
  public void trRange(
    &.Var v, bool not, bool minequ, &.Var min, &.Var max, bool maxequ)
  {
    bool b1 = (minequ ? `trGrE(v, min) : `trGr(v, min))$.v.isT();
    bool b2 = (maxequ ? `trLsE(v, max) : `trLs(v, max))$.v.isT();
    .v.setB((b1&b2) ^ not);
  }
  public void trEqu(&.Var v1, &.Var v2)
  {:<-
    void i(&.Var r=, int   i1, int   i2){r.setB(i1 == i2);}
    void f(&.Var r=, float f1, float f2){r.setB(f1 == f2);}
    `nikou!i, f?(.v=, v1, v2);
  }
  public void trNEqu(&.Var v1, &.Var v2)
  {:<-
    void i(&.Var r=, int   i1, int   i2){r.setB(i1 != i2);}
    void f(&.Var r=, float f1, float f2){r.setB(f1 != f2);}
    `nikou!i, f?(.v=, v1, v2);
  }
  public void trGr(&.Var v1, &.Var v2)
  {:<-
    void i(&.Var r=, int   i1, int   i2){r.setB(i1 > i2);}
    void f(&.Var r=, float f1, float f2){r.setB(f1 > f2);}
    `nikou!i, f?(.v=, v1, v2);
  }
  public void trGrE(&.Var v1, &.Var v2)
  {:<-
    void i(&.Var r=, int   i1, int   i2){r.setB(i1 >= i2);}
    void f(&.Var r=, float f1, float f2){r.setB(f1 >= f2);}
    `nikou!i, f?(.v=, v1, v2);
  }
  public void trLs(&.Var v1, &.Var v2)
  {:<-
    void i(&.Var r=, int   i1, int   i2){r.setB(i1 < i2);}
    void f(&.Var r=, float f1, float f2){r.setB(f1 < f2);}
    `nikou!i, f?(.v=, v1, v2);
  }
  public void trLsE(&.Var v1, &.Var v2)
  {:<-
    void i(&.Var r=, int   i1, int   i2){r.setB(i1 <= i2);}
    void f(&.Var r=, float f1, float f2){r.setB(f1 <= f2);}
    `nikou!i, f?(.v=, v1, v2);
  }
  public void trIfelse(bool b, &.Var v1, &.Var v2)
  {
    .v = b ? v1 : v2;
  }
  public void trMinus()
  {
    if(.v.isSF()) .v.setB(false);
    .v.i *= -1;
    .v.f *= -1.0;
  }
  public void trAbs()
  {
    .v.i = #.v.i;
    .v.f = #.v.f;
  }
  public void trFloor()
  {
    if(.v.typ != .VarTy::Float) ret;
    .v.setF(.m.floor(.v.f));
    if(!.v.isSF()) .v.setI(.v.toI());
  }
  public void trCeil()
  {
    if(.v.typ != .VarTy::Float) ret;
    .v.setF(.m.ceil(.v.f));
    if(!.v.isSF()) .v.setI(.v.toI());
  }
  public void trSin()
  {
    if(!.v.isSF()) .v.setF(.m.sin(.v.toF()));
  }
  public void trCos()
  {
    if(!.v.isSF()) .v.setF(.m.cos(.v.toF()));
  }
  public void trTan()
  {
    if(!.v.isSF()) .v.setF(.m.tan(.v.toF()));
  }
  public void trAsin()
  {
    if(.v.isSF()) ret;
    double x = .v.toF();
    if(!.m.inRange!double?(-1.0, 1.0, x)){
      .v.setSF();
      ret;
    }
    .v.setF(.m.asin(x));
  }
  public void trAcos()
  {
    if(.v.isSF()) ret;
    double x = .v.toF();
    if(!.m.inRange!double?(-1.0, 1.0, x)){
      .v.setSF();
      ret;
    }
    .v.setF(.m.acos(x));
  }
  public void trAtan()
  {
    if(!.v.isSF()) .v.setF(.m.atan(.v.toF()));
  }
  public void trLog(&.Var v1, &.Var v2)
  {
    double x = v2.toF(), y = v1.toF();
    if(v1.isSF() || v2.isSF() || x <= 0.0 || y <= 0.0){
      .v.setSF();
      ret;
    }
    .v.setF(.m.log(x, y));
  }
  public void trLn()
  {
    if(.v.isSF()) ret;
    double x = .v.toF();
    if(x <= 0.0){
      .v.setSF();
      ret;
    }
    .v.setF(.m.ln(x));
  }
  public void trExp()
  {
    if(!.v.isSF()) .v.setF(.m.exp(.v.toF()));
  }
  public void trMul(&.Var v1, &.Var v2)
  {:<-
    void i(&.Var r=, int   i1, int   i2){r.setI(i1 * i2);}
    void f(&.Var r=, float f1, float f2){r.setF(f1 * f2);}
    `nikou!i, f?(.v=, v1, v2);
  }
  public void trDiv(&.Var v1, &.Var v2)
  {:<-
    public void i(&.Var r=, int   i1, int   i2)
    {
      branch{
      cond i2 == 0:
        r.setSF();
      else:
        r.setI(i1 / i2);
      }
    }
    void f(&.Var r=, float f1, float f2){r.setF(f1 / f2);}
    `nikou!i, f?(.v=, v1, v2);
  }
  public void trMod(&.Var v1, &.Var v2)
  {
    int i2 = v2.toI();
    branch{
    cond i2 == 0:
      .v.setSF();
    else:
      .v.setI(v1.toI() % i2);
    }
  }
  public void trAdd(&.Var v1, &.Var v2)
  {:<-
    void i(&.Var r=, int   i1, int   i2){r.setI(i1 + i2);}
    void f(&.Var r=, float f1, float f2){r.setF(f1 + f2);}
    `nikou!i, f?(.v=, v1, v2);
  }
  public void trSub(&.Var v1, &.Var v2)
  {:<-
    void i(&.Var r=, int   i1, int   i2){r.setI(i1 - i2);}
    void f(&.Var r=, float f1, float f2){r.setF(f1 - f2);}
    `nikou!i, f?(.v=, v1, v2);
  }
  public void trPow(&.Var v1, &.Var v2)
  {:<-
    void i(&.Var r=, int i1, int i2)
    {//winmugenのバグの再現
      r.typ = .VarTy::Int;
      branch{
      cond i2 < 0:
        branch{
          float f = ((float)i1)**(float)i2;
        cond `stMver0() == 1:
          r.setF(f);
        else:
          .mes.veryUnsafeCopy!int, float?(r.i=, f=);
          r.i = r.i << 29;
        }
      else:
        {
          int hb = -1;
          int tmp = i1;
          loop{while; do: hb++; while (uint)i2>>(uint)(hb+1) != 0x0:}
          r.i = 1;
          loop{int bit = 0; while; do:
            if(
              (
                i2 & (int)1 << (
                  bit == hb || `stMver0() == 1 ? bit : (hb - 1) - bit))
              != 0)
            {
              r.i *= tmp;
            }
            tmp *= tmp;
            bit++;
          while bit <= hb:}
        }
      }
    }
    void f(&.Var r=, float f1, float f2){r.setF(f1**f2);}
    `nikou!i, f?(.v=, v1, v2);
  }
  public int trId()
  {
    ret `id;
  }
  public void addX(float x)
  {
    `setX(`sysfvar[.fX] + (float)`facing*x);
  }
  public void addY(float y)
  {
    `setY(`sysfvar[.fY] + y);
  }
  public void addXV(float x)
  {
    `sysfvar[.fVX] += x;
  }
  public void addYV(float y)
  {
    `sysfvar[.fVY] += y;
  }
  public void mulXV(float x)
  {
    `sysfvar[.fVX] *= x;
  }
  public void mulYV(float y)
  {
    `sysfvar[.fVY] *= y;
  }
  public int trAnimTime()
  {
    if(#`ani == 0 || #`ani~ani.frames == 0) ret 0;
    ret `ani~ani.animTime();
  }
  public void trAnimElemTime(int e)
  {
    if(e < 1 || #`ani == 0 || e > #`ani~ani.frames){
      .v.setSF();
      ret;
    }
    .v.setI(`ani~ani.animElemTime(e));
  }
  public void trAnimElemNo(int tim)
  {
    if(#`ani == 0 || tim < -`ani~ani.sumtime){
      .v.setSF();
      ret;
    }
    .v.setI(`ani~ani.animElemNo(tim));
  }
  public void trChangeAnim(int no)
  {
    *`ani.self tmp = `getAction(no);
    if(#tmp == 0) ret;
    `ani = tmp;
    `animno = no;
    `animpno = `playerno;
    `sysfvar[.fCLSNXSCALE] = .chars[`playerno]<>~sysfvar[.fXSCALE];
    `sysfvar[.fCLSNYSCALE] = .chars[`playerno]<>~sysfvar[.fYSCALE];
    if(`isHitPaused()) `curFrame = `ani~ani.currentFrame();
  }
  public void trChangeAnim2(int no)
  {
    *`ani.self tmp = .chars[`stVal.playerno][0]~getAction(no);
    if(#tmp == 0) ret;
    `ani = tmp;
    `animno = no;
    `animpno = `stVal.playerno;
    `sysfvar[.fCLSNXSCALE] = .chars[`stVal.playerno][0]~sysfvar[.fXSCALE];
    `sysfvar[.fCLSNYSCALE] = .chars[`stVal.playerno][0]~sysfvar[.fYSCALE];
    `ani~ani.sff = .cgi[`playerno].sf;
    if(`isHitPaused()) `curFrame = `ani~ani.currentFrame();
  }
  public void setAnimElem(int e)
  {
    if(#`ani > 0){
      `ani~ani.setAnimElem(e);
      `curFrame = `ani~ani.currentFrame();
    }
  }
  public void trAnimExist(int pid)
  {
    if(.v.isSF()) ret;
    .v.setB(
      #.chars[`id == pid ? `stVal.playerno : `playerno][0]~getAction(.v.toI())
      > 0);
  }
  public void trSelfAnimExist()
  {
    if(.v.isSF()) ret;
    .v.setB(#`getAction(.v.toI()) > 0);
  }
  public void trPlayerIDExist()
  {
    if(.v.isSF()) ret;
    .v.setB(#.players.get(.v.toI()) > 0);
  }
  public void trSysIVar(int idx)
  {
    if(idx < 0 || (`minus != 11 && idx >= 5)){
      .v.setSF();
      ret;
    }
    .v.setI(`sysivar[idx]);
  }
  public int trSetSysIVar(int idx, int v)
  {
    if(idx >= 0 && (`minus == 11 || idx < 5)) `sysivar[idx] = v;
    ret v;
  }
  public int trAddSysIVar(int idx, int v)
  {
    if(idx >= 0 && (`minus == 11 || idx < 5)) `sysivar[idx] += v;
    ret v;
  }
  public void trSysFVar(int idx)
  {
    if(idx < 0 || (`minus != 11 && idx >= 5)){
      .v.setSF();
      ret;
    }
    .v.setF(`sysfvar[idx]);
  }
  public float trSetSysFVar(int idx, float v)
  {
    if(idx >= 0 && (`minus == 11 || idx < 5)) `sysfvar[idx] = v;
    ret v;
  }
  public float trAddSysFVar(int idx, float v)
  {
    if(idx >= 0 && (`minus == 11 || idx < 5)) `sysfvar[idx] += v;
    ret v;
  }
  public void trIVar(int idx)
  {
    if(idx < 0 || idx >= 60){
      .v.setSF();
      ret;
    }
    .v.setI(`ivar[idx]);
  }
  public int trSetIVar(int idx, int v)
  {
    if(idx >= 0 && idx < 60) `ivar[idx] = v;
    ret v;
  }
  public int trAddIVar(int idx, int v)
  {
    if(idx >= 0 && idx < 60) `ivar[idx] += v;
    ret v;
  }
  public void trFVar(int idx)
  {
    if(idx < 0 || idx >= 40){
      .v.setSF();
      ret;
    }
    .v.setF(`fvar[idx]);
  }
  public float trSetFVar(int idx, float v)
  {
    if(idx >= 0 && idx < 40) `fvar[idx] = v;
    ret v;
  }
  public float trAddFVar(int idx, float v)
  {
    if(idx >= 0 && idx < 40) `fvar[idx] += v;
    ret v;
  }
  public bool changeState1(int p, int n)
  {:<-
    if(.changeStateNest >= 2500){
      %char buf .=
        "2500 loops: " .= `name .= ", " .= ''`stVal.prevno .= " -> "
        .= ''`stVal.no .= " -> " .= ''n;
      .al.alert!self?(buf);
      ret false;
    }
    `stVal.prevno = `stVal.no;
    if(`stVal.playerno != `playerno && p != `stVal.playerno){
      `enemyExplodsRemove(`stVal.playerno);
    }
    `stVal.no = .m.max!int?(0, n);
    `stVal.playerno = p;
    `stVal.time = 0;
    ^&`State st = .states[`stVal.playerno].get(`stVal.no);
    `stateDef = #st > 0 ? st~stateDef : `dummy;
    `state = #st > 0 ? st~state : `dummy;
    `cs1tmp = true;
    ret true;
  }
  public void changeState2()
  {
    if(`cs1tmp && !`isHitPaused()){
      `stateDef(::);
      `cs1tmp = false;
    }
  }
  public void trChangeState2(int n, int p, int anim, int ctrl)
  {
    if(!`ls(.lsNOAUTOTURN) && `minus <= 0 && (`stVal.typ == .StTy::S || `stVal.typ == .StTy::C)){
      `furimuki();
    }
    if(anim >= 0) `trChangeAnim(anim);
    if(ctrl >= 0) `setCtrl(ctrl != 0);
    if(`changeState1(p, n) && `minus == 0){
      `changeState2();
      .changeStateNest++;
      `state(::);
      .changeStateNest--;
    }
  }
  public void trChangeState(int no, int anim, int ctrl)
  {
    `trChangeState2(no, `stVal.playerno, anim, ctrl);
  }
  public void trSelfState(int no, int anim, int ctrl)
  {
    `trChangeState2(no, `playerno, anim, ctrl);
  }
  bool commandSub(int pno, int i)
  {
    ^&.cmd.Command cl = `cmd[pno].at(i);
    if(#cl > 0 && `key < 0){
      if(`mver0() == 1 && `helperindex != 0) ret false;
      ^/char name = cl~name;
      if(
        `helperindex == 0 && #cl~cmd == 1 && #cl~cmd~key == 1
        && (int)cl~cmd~slash == #cl~hold)
      {
        if(`helperindex != 0) ret false;
        break, break;
      }
      ret i == `cpucmd;
    }
    loop{index i = 0; while; do:
      if(cl[i].curbuftime > 0) ret true;
      i++;
    while i < #cl:}
    ret false;
  }
  public bool commandByName(^/char name)
  {
    if(!`keyctrl || #`cmd == 0) ret false;
    ^index ci = `cmd[`stVal.playerno].cTable~get(name);
    if(#ci == 0) ret false;
    ret `commandSub(`stVal.playerno, ci<>);
  }
  public bool trCommand(int pno, int i)
  {
    ret `keyctrl && #`cmd > 0 && `commandSub(pno, i);
  }
  public ^self getP2()
  {
    ^`self e = .players.enemyNear(`=, 0, true);
    if(#e > 0 && e~isKO() && e~sf(.sfOVER)){
      e.new(0);
    }
    ret e;
  }
  public void trP2Life()
  {
    ^`self e = `getP2();
    if(#e == 0){
      .v.setSF();
      ret;
    }
    .v.setI(e~sysivar[.iLIFE]);
  }
  public void trTurn()
  {
    `setFacing(-`facing);
  }
  public void trDistX(^`self c)
  {
    if(#c == 0){
      .v.setSF();
      ret;
    }
    float dist = (float)`facing * `distX(c<>=);
    .v.setF(`stMver0() == 1 ? dist : (float)(int)dist);
  }
  public void trP2DistX()
  {
    `trDistX(`getP2());
  }
  public void trP2DistY()
  {
    ^`self e = `getP2();
    if(#e == 0){
      .v.setSF();
      ret;
    }
    .v.setF(e~sysfvar[.fY] - `sysfvar[.fY]);
  }
  public void trP2BodyDistX()
  {
    ^`self e = `getP2();
    if(#e == 0){
      .v.setSF();
      ret;
    }
    float dist = (float)`facing * `bodyDistX(e<>=);
    .v.setF(`stMver0() == 1 ? dist : (float)(int)dist);
  }
  public void trRootDistX()
  {
    if(`helperindex == 0){
      .v.setSF();
      ret;
    }
    float dist = (float)`facing * `distX(.chars[`playerno]<><>=);
    .v.setF(`stMver0() == 1 ? dist : (float)(int)dist);
  }
  public void trRootDistY()
  {
    if(`helperindex == 0){
      .v.setSF();
      ret;
    }
    .v.setF(.chars[`playerno][0]~sysfvar[.fY] - `sysfvar[.fY]);
  }
  public void trParentDistX()
  {
    `trParent();
    `trDistX(.c);
  }
  public void trParentDistY()
  {
    `trParent();
    if(#.c == 0){
      .v.setSF();
      ret;
    }
    .v.setF(.c~sysfvar[.fY] - `sysfvar[.fY]);
  }
  public bool trStateType(|.StTy st)
  {
    ret st == `stVal.typ;
  }
  public void trP2StateType(|.StTy st)
  {
    ^`self e = `getP2();
    if(#e == 0){
      .v.setSF();
      ret;
    }
    .v.setB(st == e~stVal.typ);
  }
  public void trP2StateNo()
  {
    ^`self e = `getP2();
    if(#e == 0){
      .v.setSF();
      ret;
    }
    .v.setI(e~stVal.no);
  }
  public bool trMoveType(|.MovTy mt)
  {
    ret mt == `stVal.mov;
  }
  public void trP2MoveType(|.MovTy mt)
  {
    ^`self e = `getP2();
    if(#e == 0){
      .v.setSF();
      ret;
    }
    .v.setB(mt == e~stVal.mov);
  }
  public float distX(`self c=)
  {
    ret c.sysfvar[.fX] - `sysfvar[.fX];
  }
  public float bodyDistX(`self c=)
  {
    float dist = `distX(c=);
    bool bar = dist == 0.0 || (dist < 0.0) ^ (c.facing < 0);
    ret
      (dist + (float)c.facing * (bar ? c.frontw : -c.backw))
      - (float)`facing * `frontw;
  }
  public bool trPName(int no, ^/char name)
  {:<-
    if(no <= 0 || #.chars < no) ret false;
    if((no & 1) == 0){
      ^`self e = .players.enemyNear(`=, (no >> 1) - 1, true);
      ret
        #e > 0 && !(e~isKO() && e~sf(.sfOVER))
        && .s.equ(name, .cgi[e~playerno].nameLow);
    }
    int foo;
    branch{
    cond (no & 1) == 1 && no - 1 <= `playerno:
      branch{
      cond no == 1:
        foo = `playerno;
      else:
        foo = ((no - 1) - 2) + (`playerno & 1);
      }
    else:
      foo = (no - 1) ^ (`playerno & 1);
    }
    ret #.chars[foo] > 0 && .s.equ(name, .cgi[foo].nameLow);
  }
  public bool trAuthor(^/char name)
  {
    ret .s.equ(name, .cgi[`playerno].authorLow);
  }
  public int trFrontEdgeDist()
  {
    ret
      (int)(
        `facing > 0 ? .com.xmax - `sysfvar[.fX] : `sysfvar[.fX] - .com.xmin);
  }
  public int trFrontEdgeBodyDist()
  {
    ret
      (int)(
        (`facing > 0 ? .com.xmax - `sysfvar[.fX] : `sysfvar[.fX] - .com.xmin)
        - `getEdge(`fedge, false));
  }
  public float trFrontEdge()
  {
    ret `facing > 0 ? `trRightEdge() : `trLeftEdge();
  }
  public int trBackEdgeDist()
  {
    ret
      (int)(
        `facing < 0 ? .com.xmax - `sysfvar[.fX] : `sysfvar[.fX] - .com.xmin);
  }
  public int trBackEdgeBodyDist()
  {
    ret
      (int)(
        (`facing < 0 ? .com.xmax - `sysfvar[.fX] : `sysfvar[.fX] - .com.xmin)
        - `getEdge(`bedge, false));
  }
  public float trBackEdge()
  {
    ret `facing < 0 ? `trRightEdge() : `trLeftEdge();
  }
  public float trLeftEdge()
  {
    ret .com.cam.screenX + .com.CharGameLeft / .com.cam.scale;
  }
  public float trRightEdge()
  {
    ret .com.cam.screenX + .com.CharGameRight / .com.cam.scale;
  }
  public float trTopEdge()
  {
    ret .com.cam.screenY;
  }
  public float trBottomEdge()
  {
    ret .com.cam.screenY + `trGameHeight();
  }
  public float trGameWidth()
  {
    ret .com.CharGameWidth / .com.cam.scale;
  }
  public float trGameHeight()
  {
    ret 240.0 / .com.cam.scale;
  }
  public float trScreenWidth()
  {
    ret .com.CharGameWidth;
  }
  public float trScreenHeight()
  {
    ret 240.0;
  }
  public float trCameraPosX()
  {
    ret .com.cam.x;
  }
  public float trCameraPosY()
  {
    ret .com.cam.y;
  }
  public float trCameraZoom()
  {
    ret .com.cam.scale;
  }
  public void trIsHelper()
  {
    if(.v.isSF()) ret;
    int id = .v.toI();
    .v.setB(`helperindex != 0 && (id <= 0 || `helperid == id));
  }
  public bool trTeamMode(|.com.TeamMode tm)
  {
    ret .com.tmode[`playerno&1] == (int)tm;
  }
  public void trNewHelper(^`self c=)
  {
    c = .create(`playerno);
    if(#c == 0) ret;
    c~helperid = 0;
    c~copyParent(`=);
    `addChild(c~helperindex);
  }
  void helproSetPos<_t>(_t obj=, int pt, float x, float y, int facing)
  {
    switch(pt){
    case 2, 3://front, back
      if(facing < 0) obj.facing *= -1;
      branch{
      cond (`facing > 0 && pt == 2) || (`facing < 0 && pt == 3):
        obj.setX(`trRightEdge() - x * (pt == 2 ? -1.0 : 1.0));
      else:
        obj.setX(`trLeftEdge() + x*(pt == 2 ? -1.0 : 1.0));
      }
      obj.setY(y);
      obj.facing *= `facing;
    case 4://left
      if(facing < 0) obj.facing *= -1;
      obj.setX(`trLeftEdge() + x);
      obj.setY(y);
    case 5://right
      if(facing < 0) obj.facing *= -1;
      obj.setX(`trRightEdge() + x);
      obj.setY(y);
    default:
      `setPos!_t?(obj=, pt, x, y, facing);
    }
  }
  public void trHelperInit(
    `self h=, int st, int pt, float x, float y, int facing, int ownpal)
  {
    `helproSetPos!h.self?(h=, pt, x, y, facing);
    h.sysfvar[.fVX] = h.sysfvar[.fVY] = 0.0;
    if(ownpal != 0){
      h.palfx.new(1);
      h.palfx~remap = `getPalMap() + (index)[];
    }
    h.trChangeState2(st, `playerno, 0, 1);
  }
  public void trProjInit(
    &.Projectile p=, int pt, float x, float y, bool op, int rpg, int rpi)
  {
    `helproSetPos!p.self?(p=, pt, x, y, 1);
    if(p.anim < -1) p.anim = 0;
    p.ani = `getAction(p.anim);
    if(#p.ani == 0 && #`ani > 0){
      p.ani.new(1);
      p.ani~copy(`ani<>=);
      p.ani~ani.setAnimElem(1);
      p.anim = p.ani~no;
    }
    if(#p.ani > 0) p.ani~ani.updateSprite();
    if(`sysivar[.iPROJ_DOSCALE] != 0){
      p.scalex *= `sysfvar[.fXSCALE];
      p.scaley *= `sysfvar[.fYSCALE];
    }
    p.clsnscalex = `sysfvar[.fXSCALE];
    p.clsnscaley = `sysfvar[.fYSCALE];
    if(p.velocityx < 0.0){
      p.facing *= -1;
      p.velocityx *= -1.0;
      p.accelx *= -1.0;
    }
    if(op){
      %index remap .= p.palfx~remap;
      p.palfx.new(1);
      p.palfx~remap = remap;
      `remapPalSub(p.palfx, 1, 1, rpg, rpi);
    }
  }
  public void trDestroySelf(bool recursive, bool removeexplods)
  {
    if(`helperindex <= 0) ret;
    `sysivar[.iSPECIALFLAG] |= .lsDESTROY;
    if(removeexplods) `trRemoveExplod(-1);
    if(recursive) `children:<-[void(c=){
      if(c >= 0) .chars[`playerno][c]~trDestroySelf(recursive, removeexplods);
    }];
  }
  public %int getTarget(int id)
  {
    if(id < 0) ret `targets;
    %int tar;
    ^`self c;
    `targets:<-[void(t){
      c = .players.get(t);
      if(#c > 0 && c~stVal.hb.hitid == id) tar .= t;
    }];
    ret tar;
  }
  public void trTargetBind(^/int tar, int time, float x, float y)
  {
    ^`self c;
    tar:<-[void(t){
      c = .players.get(t);
      if(#c > 0){
        c~setBindToId(`=);
        c~setBindTime(time);
        c~sysivar[.iBINDFACING] = 0;
        c~sysfvar[.fBINDPOSX] = x;
        c~sysfvar[.fBINDPOSY] = y;
      }
    }];
  }
  public void trBindToTarget(^/int tar, int time, float x, float y, int hmf)
  {
    if(#tar == 0) ret;
    ^`self c = .players.get(tar<>);
    if(#c == 0) ret;
    float bx = x, by = y;
    switch(hmf){
    case 1:
      bx += (float)c~sysivar[.iMID_POSX];
      by += (float)c~sysivar[.iMID_POSY];
    case 2:
      bx += (float)c~sysivar[.iHEAD_POSX];
      by += (float)c~sysivar[.iHEAD_POSY];
    }
    if(!.m.isnan(bx)) `setX(c~sysfvar[.fX] + (float)c~facing*bx);
    if(!.m.isnan(by)) `setY(c~sysfvar[.fY] + by);
    `trTargetBind(
      tar[0..1], time, (float)`facing*`distX(c<>=),
      c~sysfvar[.fY] - `sysfvar[.fY]);
  }
  public void setBindFacing(int f)
  {
    if(f== 0) ret;
    `sysivar[.iBINDFACING] = f < 0 ? (int)-1 : 1;
  }
  public void trTargetDrop(int id, bool keepone)
  {
    %int tmp;
    ^`self c;
    loop{
      if(id < 0){
        tmp = `targets;
        break, break;
      }
      index i = 0;
      while;
    do:
      c = .players.get(`targets[i]);
      if(#c > 0) branch{
      cond c~stVal.hb.hitid == id:
        tmp .= `targets[i];
      else:
        c~byBindClear();
        c~stVal.hb.dropByid(`id);
      }
      i++;
    while i < #`targets:}
    branch{
    cond (keepone || id < 0) && #tmp > 0:
      `targets.new(0);
      loop{
        index i = 0, r = keepone && id >= 0 ? .m.rand(0, #tmp-1) : -1;
        while;
      do:
        branch{
        cond  i == r:
          `targets .= tmp[i];
        else:
          c = .players.get(tmp[i]);
          if(#c > 0){
            c~byBindClear();
            c~stVal.hb.dropByid(`id);
          }
        }
        i++;
      while i < #tmp:}
    else:
      `targets = tmp;
    }
  }
  public void trTargetFacing(^/int tar, int fasing)
  {
    if(fasing == 0) ret;
    int f = `facing;
    if(fasing < 0) f *= -1;
    ^`self c;
    tar:<-[void(t){
      c = .players.get(t);
      if(#c > 0) c~setFacing(f);
    }];
  }
  public void trTargetState(^/int tar, int state)
  {
    if(state < 0) ret;
    ^`self c;
    int pno = `minus == -2 ? `playerno : `stVal.playerno;
    tar:<-[void(t){
      c = .players.get(t);
      if(#c > 0){
        c~setCtrl(false);
        c~changeState1(pno, state);
      }
    }];
  }
  public void trTargetVelSetX(^/int tar, float vx)
  {
    ^`self c;
    tar:<-[void(t){
      c = .players.get(t);
      if(#c > 0) c~setXV(vx);
    }];
  }
  public void trTargetVelSetY(^/int tar, float vy)
  {
    ^`self c;
    tar:<-[void(t){
      c = .players.get(t);
      if(#c > 0) c~setYV(vy);
    }];
  }
  public void trTargetVelAddX(^/int tar, float vx)
  {
    ^`self c;
    tar:<-[void(t){
      c = .players.get(t);
      if(#c > 0) c~sysfvar[.fVX] += vx;
    }];
  }
  public void trTargetVelAddY(^/int tar, float vy)
  {
    ^`self c;
    tar:<-[void(t){
      c = .players.get(t);
      if(#c > 0) c~sysfvar[.fVY] += vy;
    }];
  }
  public void trTargetLifeAdd(^/int tar, int va, bool kill, bool absolute)
  {
    ^`self c;
    tar:<-[void(t){
      if(#(c = .players.get(t)) > 0){
        c~addLife(
          -(double)c~getDamage(-(double)va, kill, absolute, 1.0), true, true);
      }
    }];
  }
  public void trTargetPowerAdd(^/int tar, int pw)
  {
    ^`self c;
    tar:<-[void(t){
      c = .players.get(t);
      if(#c > 0 && c~player) c~addPower(pw);
    }];
  }
  public void trHitAdd(int h)
  {
    `sysivar[.iHITCOUNT] += h;
    ^`self c;
    `targets:<-[void(t){
      c = .players.get(t);
      if(#c > 0) c~getcombo += h;
    }];
  }
  public int  trNumEnemy()
  {
    int ep = !`playerno & 1;
    ret .com.tmode[ep] == (int).com.TeamMode::Simul ? .com.numSimul[ep] : 1;
  }
  public int trNumPartner()
  {
    if(.com.tmode[`playerno&1] != (int).com.TeamMode::Simul) ret 0;
    ret .com.numSimul[`playerno&1] - 1;
  }
  public float trHitXvel()
  {
    ret `stVal.hb.xvel * (float)`facing;
  }
  public float trFallXvel()
  {
    if(.m.isnan(`stVal.hb.fall.xvelocity)) ret -32760.0;
    ret `stVal.hb.fall.xvelocity;
  }
  public void trHitFallSet(int f, float vx, float vy)
  {
    if(`stVal.mov != .MovTy::H) ret;
    if(f >= 0) `stVal.hb.fallf = f != 0;
    if(!.m.isnan(vx)) `stVal.hb.fall.xvelocity = vx;
    if(!.m.isnan(vy)) `stVal.hb.fall.yvelocity = vy;
  }
  public void trHitFallVel()
  {
    if(`stVal.mov != .MovTy::H) ret;
    if(!.m.isnan(`stVal.hb.fall.xvelocity)) `setXV(`stVal.hb.fall.xvelocity);
    `setYV(`stVal.hb.fall.yvelocity);
  }
  public void trHitFallDamage()
  {
    if(`stVal.mov != .MovTy::H) ret;
    `addLife(-(double)`stVal.hb.fall.damage, `stVal.hb.fall.kill != 0, false);
  }
  public void trHitVelSetX()
  {
    if(`stVal.mov != .MovTy::H) ret;
    `setXV(`stVal.hb.xvel);
  }
  public void trHitVelSetY()
  {
    if(`stVal.mov != .MovTy::H) ret;
    `setYV(`stVal.hb.yvel);
  }
  public float trHitVelX()
  {
    ret `stVal.mov == .MovTy::H ? -`stVal.hb.xvel : 0.0;
  }
  public float trHitVelY()
  {
    ret `stVal.mov == .MovTy::H ? -`stVal.hb.yvel : 0.0;
  }
  public int trHitId()
  {
    ret `stVal.hb.hitid > 0 ? `stVal.hb.hitid : 0;
  }
  public void trProjTime(|.ProjContact pct)
  {
    if(.v.isSF()) ret;
    int id = .v.toI();
    .v.setI(
      (id <= 0  || id == .cgi[`playerno].pcid)
      && .cgi[`playerno].pctyp == pct
      ? .cgi[`playerno].pctime : -1);
  }
  public void trProjContactTime()
  {
    if(.v.isSF()) ret;
    int id = .v.toI();
    .v.setI(
      id <= 0 || id == .cgi[`playerno].pcid ? .cgi[`playerno].pctime : -1);
  }
  public bool trHitDefAttr(int flg)
  {
    const int mask = (int).AtTy::NA - 1;
    int attr = `stVal.hit.attr & (int)0x7fffffff;
    ret 
      `stVal.mov == .MovTy::A
      && (mask & attr & flg) != 0  && (!mask & attr & flg) != 0;
  }
  public void trNumHelper()
  {
    if(.v.isSF()) ret;
    int id = .v.toI();
    .v.typ = .VarTy::Int;
    .v.i = 0;
    .chars[`playerno]:<-[void(h=){
      if(
        h~helperindex > 0 && !h~ls(.lsDESTROY)
        && (id <= 0 || id == h~helperid)) .v.i++;
    }];
  }
  public bool matchExplodId(index i, int id)
  {
    ret
      .explods[`playerno][i].id >= 0 && (
        .explods[`playerno][i].player == `id
        && (id < 0 || .explods[`playerno][i].id == id));
  }
  public void trExplodBindTime(int id, int bt)
  {
    loop{index i = 0; while; do:
      if(`matchExplodId(i, id)){
        .explods[`playerno][i].bindtime = bt;
      }
      i++;
    while i < #.explods[`playerno]:}
  }
  public void trRemoveExplod(int id)
  {:<-
    void expRemove(int id, ^%index drawlist=, bool delI)
    {
      loop{index i = #drawlist[`playerno]-1; while; do:
        if(drawlist[`playerno][i] < 0) continue;
        if(`matchExplodId(drawlist[`playerno][i], id)){
          .explods[`playerno][drawlist[`playerno][i]].id = .com.IERR;
          branch{
          cond delI:
            .delIL(drawlist[`playerno]=, i);
          else:
            drawlist[`playerno][i] = -1;
          }
        }
      continue:
        i--;
      while i >= 0:}
    }
    expRemove(id, .expdrawlist=, true);
    expRemove(id, .topexpdrawlist=, false);
  }
  public void trNumExplod()
  {
    if(.v.isSF()) ret;
    int id = .v.toI();
    .v.typ = .VarTy::Int;
    .v.i = 0;
    loop{index i = 0; while; do:
      if(`matchExplodId(i, id)) .v.i++;
      i++;
    while i < #.explods[`playerno]:}
  }
  public void trNumTarget()
  {
    if(.v.isSF()) ret;
    int id = .v.toI();
    .v.typ = .VarTy::Int;
    .v.i = 0;
    `targets:<-[void(tar){
      if(tar >= 0) branch{
      cond id < 0:
        .v.i++;
      else:
        {
          ^`self t = .players.get(tar);
          if(#t > 0 && t~stVal.hb.hitid == id) .v.i++;
        }
      }
    }];
  }
  public void trNumProjID()
  {
    if(.v.isSF()) ret;
    int id = .v.toI();
    if(`helperindex != 0){
      .v.setI(0);
      ret;
    }
    int d = .m.max!int?(0, id);
    .v.typ = .VarTy::Int;
    .v.i = 0;
    .projs[`playerno]:<-[void(p=){
      if(p.id == d && p.hits >= 0) .v.i++;
    }];
  }
  public int trNumProj()
  {
    int n = 0;
    .projs[`playerno]:<-[void(p=){
      if(p.id >= 0 && p.hits >= 0) n++;
    }];
    ret n;
  }
  public int trHitPauseTime()
  {
    ret `sysivar[.iHITPAUSETIME];
  }
  public bool trHitOver()
  {
    ret `stVal.hb.hittime < 0;
  }
  public bool trHitShakeOver()
  {
    ret `stVal.hb.hitshaketime <= 0;
  }
  public bool trCanRecover()
  {
    ret
      `stVal.hb.fall.recover != 0
      && `stVal.fallTime >= `stVal.hb.fall.recovertime;
  }
  public int trMoveContact()
  {
    ret `stVal.mctyp != .MoveContact::Reversed ? #`stVal.mctime : 0;
  }
  public int trMoveReversed()
  {
    ret `stVal.mctyp == .MoveContact::Reversed ? #`stVal.mctime : 0;
  }
  public int trMoveHit()
  {
    ret `stVal.mctyp == .MoveContact::Hit ? #`stVal.mctime : 0;
  }
  public int trMoveGuarded()
  {
    ret `stVal.mctyp == .MoveContact::Guarded ? #`stVal.mctime : 0;
  }
  public int trMatchNo()
  {
    ret .com.match;
  }
  public int trRoundsExisted()
  {
    ret .com.rexisted[`playerno&1];
  }
  public bool isWin()
  {
    ret (`playerno&1) == .com.win;
  }
  public bool isLose()
  {
    ret (!`playerno&1) == .com.win;
  }
  public bool isOver()
  {
    ret
      `sf(.sfOVER) || (
        `ctrlOver() && `ctrl
        && `stVal.typ != .StTy::A && `stVal.phy != .StTy::A);
  }
  public bool trWinKO()
  {
    ret `isWin() && .ko == .fgt.KOTy::KO;
  }
  public bool trWinTime()
  {
    ret `isWin() && .ko == .fgt.KOTy::TO;
  }
  public bool trWinPerfect()
  {
    ret `isWin() && .winty[`playerno&1] >= .fgt.WinTy::PN;
  }
  public bool trLoseKO()
  {
    ret `isLose() && .ko == .fgt.KOTy::KO;
  }
  public bool trLoseTime()
  {
    ret `isLose() && .ko == .fgt.KOTy::TO;
  }
  public bool trDrawGame()
  {
    ret `roundState() >= 3 && .com.win < 0;
  }
  public void remapPalSub(^&.com.PalFX pfx, int sg, int sn, int dg, int dn)
  {
    if(sg < 0 || sn < 0 || dg < 0 || dn < 0) ret;
    ^index si =
      .cgi[`playerno].sf~palList.palTable.get((uint)sg << 0d16 | (ushort)sn);
    ^index di =
      .cgi[`playerno].sf~palList.palTable.get((uint)dg << 0d16 | (ushort)dn);
    if(#si == 0) ret;
    if(#di == 0) di = si;
    if(#pfx~remap == 0) pfx~remap = .cgi[`playerno].sf~palList.getPalMap();
    .cgi[`playerno].sf~palList.swapPalMap(pfx~remap=);
    .cgi[`playerno].sf~palList.remap(si<>, di<>);
    if(sg == 1 && sn == 1 && .cgi[`playerno].sf~head.ver0 == 0d1){
      ^&.sff.Sprite spr = .cgi[`playerno].sf~getSprite(0, 0);
      if(#spr > 0) .cgi[`playerno].sf~palList.remap(spr~palidx, di<>);
      spr = .cgi[`playerno].sf~getSprite(9000, 0);
      if(#spr > 0) .cgi[`playerno].sf~palList.remap(spr~palidx, di<>);
    }
    .cgi[`playerno].sf~palList.swapPalMap(pfx~remap=);
  }
  public void trRemapPal(int sg, int sn, int dg, int dn)
  {
    `remapPalSub(`getPalfx(), sg, sn, dg, dn);
  }
  public int trAILevel()
  {
    ret `mver0() != 1 || `helperindex == 0 ? .com.com[`playerno] : 0;
  }
}

public void Explod::update(bool oVer, int playerNo)
{
  if(#`ani == 0) `id = .com.IERR;
  if(`id == .com.IERR) ret;
  ^&.Char c;
  if(`ignorehitpause == 0 || `removeongethit != 0) c = .players.get(`player);
  bool p = false;
  branch{
  cond .super > 0:
    p = `supermovetime >= 0 && `time >= `supermovetime;
  cond .pause > 0:
    p = `pausemovetime >= 0 && `time >= `pausemovetime;
  }
  bool act = !p;
  if(act && `ignorehitpause == 0) act = #c == 0 || c~acttmp%2 != -1;
  if(.com.tickFrame()){
    if(
      (#c > 0 && `removeongethit != 0 && c~stVal.mov == .MovTy::H)
      || (`removetime >= 0 && `time >= `removetime)
      || (act && `removetime <= -2 && `ani~ani.loopend))
    {
      `id = .com.IERR;
      ret;
    }
  }
  bool screen = false;
  branch{
  cond `bindtime != 0:
    branch{
    cond `postype == 6:
      `x = `offsetx;
      `y = `offsety;
    cond `postype >= 4:
      screen = true;
      `x =
        `offsetx + (
          `postype == 4 ? .com.CharGameLeft - (float).com.GameWidth/2.0
          : (float).com.GameWidth/2.0 - .com.CharGameLeft);
      `y = `offsety;
    else:
      {
        ^&.Char bc = .players.get(`bindid);
        if(#bc == 0){
          `bindtime = 0;
          break, break;
        }
        `x = bc~drawX+bc~offsetX() + `offsetx;
        `y = bc~drawY+bc~offsetY() + `offsety;
      }
    }
  else:
    {
      float sp = .com.tickInterpola();
      `x = `ticNewX - (`ticNewX - `ticOldX) * (1.0 - sp);
      `y = `ticNewY - (`ticNewY - `ticOldY) * (1.0 - sp);
    }
  }
  if(.com.tickFrame() && act) `ani~ani.updateSprite();
  branch{
    type _t = $void(.anims.self=);
    ~_t aal = [_t(a=){
      ^&.com.PalFX pfx;
      branch{
      cond `ani~ani.sff != .fight~fsf:
        pfx = `palfx;
      cond `ownpal == 0:
        pfx.new(1);
        pfx~copy(`palfx<>);
        pfx~remap.new(0);
      }
      .addAnimList(
        a=, `ani, `sprpriority, `x, `y, screen,
        (float)`facing*`scalex, (float)`vfacing*`scaley,
        `facing < 0 == `vfacing < 0 ? `angle : -`angle,
        oVer, 1.0, 1.0, `alphas < 0 ? (int)-1 : `alphas,
        `alphad, playerNo == .superplayer,
        pfx, `shadowr<<16 | (`shadowg&255)<<8 | (`shadowb&255),
        `alphas < 0 ? 256 : `alphas, 0.0, 0.0);
    }];
  cond `ontop != 0:
    aal(:.topanims=:);
  else:
    aal(:.anims=:);
  }
  if(.com.tickNextFrame()){
    if(`bindtime > 0){
      `bindtime--;
      if(screen && `bindtime == 0) switch(`postype){
      case 4://left
        `x =
          .com.cam.screenX + (.com.CharGameLeft + `offsetx) / .com.cam.scale;
        `y = .com.cam.screenY + `offsety / .com.cam.scale;
      case 5://right
        `x =
          .com.cam.screenX + (.com.CharGameRight + `offsetx) / .com.cam.scale;
        `y = .com.cam.screenY + `offsety / .com.cam.scale;
      }
    }
    if(!act){
      `setX(`x);
      `setY(`y);
      break, break;
    }
    if(`bindtime == 0){
      `ticOldX = `x;
      `ticNewX = `x + `velocityx * (float)(`facing * `relativef);
      `ticOldY = `y;
      `ticNewY = `y + `velocityy;
      `velocityx += `accelx;
      `velocityy += `accely;
    }
    `ani~ani.action();
    `time++;
  }
}
public void Explod::setPos(&.Char c=)
{
  switch(`postype){
  case 0:
    `bindid = c.id;
    `facing = c.facing*`relativef;
    `offsetx *= (float)c.facing;
    `setX(c.sysfvar[.fX]+c.offsetX() + `offsetx);
    `setY(c.sysfvar[.fY]+c.offsetY() + `offsety);
    if(`bindtime == 0) `bindtime = 1;
  case 1:
    {
      ^&.Char bc = .players.enemyNear(c=, 0, true);
      if(#bc == 0) break;
      `bindid = bc~id;
      `facing *= bc~facing*`relativef;
      `offsetx *= (float)bc~facing;
      `setX(bc~sysfvar[.fX]+bc~offsetX() + `offsetx);
      `setY(bc~sysfvar[.fY]+bc~offsetY() + `offsety);
      if(`bindtime == 0) `bindtime = 1;
    }
  case 2, 3:
    branch{
    cond (c.facing > 0 && `postype == 2) || (c.facing < 0 && `postype == 3):
      if(`postype == 3) `offsetx *= -1.0;
      `postype = 5;
    else:
      if(`postype == 2 && c.mver0() != 1){
        `postype = 4;
        c.setPos!`self?(`=, `postype, `offsetx, `offsety, `relativef);
        break, break;
      }
      `postype = 4;
    comm:
      c.setPos!`self?(`=, `postype, `offsetx, `offsety, `relativef*c.facing);
    }
  default:
    c.setPos!`self?(`=, `postype, `offsetx, `offsety, `relativef);
  }
}
public void Explod::modify(
  &.Char c=, &.ModifyExplod mod=, index i, int rpg, int rpi)
{
  if(!c.matchExplodId(i, mod.id)) ret;
  if(`ownpal != 0) c.remapPalSub(`palfx, 1, 1, rpg, rpi);
  if(mod.bindtime != .com.IERR) `bindtime = mod.bindtime;
  if(!.m.isnan(mod.scalex)) `scalex = mod.scalex;
  if(!.m.isnan(mod.scaley)) `scaley = mod.scaley;
  if(mod.removeongethit != .com.IERR) `removeongethit = mod.removeongethit;
  if(mod.removetime != .com.IERR) `removetime = mod.removetime;
  if(!.m.isnan(mod.velocityx)) `velocityx = mod.velocityx;
  if(!.m.isnan(mod.velocityy)) `velocityy = mod.velocityy;
  if(!.m.isnan(mod.accelx)) `accelx = mod.accelx;
  if(!.m.isnan(mod.accely)) `accely = mod.accely;
  if(mod.sprpriority != .com.IERR) `sprpriority = mod.sprpriority;
  if(mod.postype != .com.IERR) `postype = mod.postype;
  if(!.m.isnan(mod.offsetx)) `offsetx = mod.offsetx;
  if(!.m.isnan(mod.offsety)) `offsety = mod.offsety;
  if(mod.relativef != .com.IERR) `relativef = mod.relativef;
  if(mod.vfacing != .com.IERR) `vfacing = mod.vfacing;
  if(mod.shadowr != .com.IERR) `shadowr = mod.shadowr;
  if(mod.shadowg != .com.IERR) `shadowg = mod.shadowg;
  if(mod.shadowb != .com.IERR) `shadowb = mod.shadowb;
  if(mod.ontop != .com.IERR) `ontop = mod.ontop;
  if(mod.alphas != .com.IERR) `alphas = mod.alphas;
  if(mod.alphad != .com.IERR) `alphad = mod.alphad;
  if(mod.supermovetime != .com.IERR) `supermovetime = mod.supermovetime;
  if(mod.pausemovetime != .com.IERR) `pausemovetime = mod.pausemovetime;
  if(mod.postype >= 0 || !.m.isnan(mod.offsetx) || !.m.isnan(mod.offsety)){
    `setPos(c=);
  }
  if(`ontop != 0) `sprpriority = 0;
  if(!.m.isnan(mod.angle)) `angle = mod.angle;
}



public ^&Char PlayerList!&Char?::get(int id)
{
  if(id < 0) ret .consts.null!`_t?();
  loop{index i = 0; while; do:
    if(.playerid[i].n == id) ret .chars[.playerid[i].pn][.playerid[i].hi];
    i++;
  while i < #.playerid:}
  loop{
    *`top.self p = `top;
    while;
  do:
    if((p~c~id == id || !p~c~id == id) && !p~c~ls(.lsDESTROY)){
      .playerid.new[-1].n = id;
      .playerid[-1].pn = p~c~playerno;
      .playerid[-1].hi = p~c~helperindex;
      ret p~c;
    }
    p = p~next;
  while #p > 0:}
  ret .consts.null!`_t?();
}
public ^&Char PlayerList!&Char?::enemyNear(&.Char pyr=, int n, bool p2)
{
  if(n < 0) ret .consts.null!pyr.self?();
  %&.RdCacheInfo enen = pyr.enemyn[(int)p2];
  loop{index i = 0; while; do:
    if(enen[i].n == n) ret .chars[enen[i].pn][enen[i].hi];
    i++;
  while i < #enen:}
  ^^pyr.self en.new(n+1);
  void add(^`pyr.self e, index rng)
  {
    loop{index i = rng; while; do:
      if(#`en[i] == 0){
        `en[i] = e;
        ret;
      }
      if(
        (`p2 && !e~isHouchied() && `en[i]~isHouchied()) || (
          (!`p2 || e~isHouchied() == `en[i]~isHouchied())
          && #`pyr.distX(e<>=) < #`pyr.distX(`en[i]<>=)))
      {
        self(`en[i], i+1);
        `en[i] = e;
        ret;
      }
      i++;
    while i < #`en:}
  }
  loop{
    *`top.self p = `top;
    while;
  do:
    if((p~c~playerno&1) != (pyr.playerno&1) && p~c~player) add(p~c, 0);
    p = p~next;
  while #p > 0:}
  if(#en[-1] == 0) ret .consts.null!&.Char?();
  enen.new[-1].n = n;
  enen[-1].pn = en[-1]~playerno;
  enen[-1].hi = en[-1]~helperindex;
  pyr.enemyn[(int)p2] = enen;
  ret en[-1];
}
public void PlayerList!&Char?::add(^&.Char c)
{:<-
  void addDO(^&.Char c){
    loop{index i = 0; while; do:
      if(#`drawOrder[i] == 0){
        `drawOrder[i] = c;
        break, break;
      }
      i++;
    while i < #`drawOrder:
      `drawOrder .= c;
    }
  }
  .playerid.new(0);
  if(#`top == 0){
    `top.new(1);
    `top~c = c;
    `end = `top;
    addDO(c);
    ret;
  }
  `end~next.new(1);
  `end = `end~next;
  `end~c = c;
  addDO(c);
}
public void PlayerList!&Char?::destroy(int id)
{:<-
  void removeDO(^&.Char c){
    loop{index i = 0; while; do:
      if(`drawOrder[i] == c){
        `drawOrder[i].new(0);
        break, break;
      }
      i++;
    while i < #`drawOrder:}
  }
  if(#`top == 0) ret;
  .playerid.new(0);
  if(`top~c~id == id){
    removeDO(`top~c);
    `top = `top~next;
    if(#`top == 0) `end.new(0);
    ret;
  }
  *`top.self p = `top;
  loop{while; do:
    if(p~next~c~id == id){
      removeDO(p~next~c);
      p~next = p~next~next;
      if(#p~next == 0) `end = p;
      break, break;
    }
    p = p~next;
  while #p~next > 0:}
}
public void PlayerList!&Char?::action(
  float x, float cvmin=, float cvmax=,
  float highest=, float lowest=, float leftest=, float rightest=)
{
  .commandUpdate();
  loop{*`top.self p = `top; while; do:
    if(p~c~stVal.mov == .MovTy::A) p~c~action();
    p = p~next;
  while #p > 0:}
  loop{*`top.self p = `top; while; do:
    p~c~action();
    p = p~next;
  while #p > 0:}
  .update(cvmin=, cvmax=, highest=, lowest=, leftest=, rightest=);
}
public void PlayerList!&Char?::update(
  float cvmin=, float cvmax=,
  float highest=, float lowest=, float leftest=, float rightest=)
{
  loop{
    *`top.self p = `top;
    while;
  do:
    p~c~update(cvmin=, cvmax=, highest=, lowest=, leftest=, rightest=);
  continue:
    p = p~next;
  while #p > 0:}
}
public void PlayerList!&Char?::clsn(&.Char pyr=, bool pro)
{
  float pxmi, pxma;
  bool foo(
    int hitting=, `pyr.self by=, &.Hitdef hit=,
    float x, float y, int pro, int hits)
  {
    void hitspark(&.Char p1=, &.Char p2=, int animNo)
    {
      ^&.act.Action ani;
      branch{
      cond animNo < 0:
        ani = .fight~getAction(!animNo);
      else:
        ani = `by.getAction(animNo);
      }
      float x =
        (float)p1.facing * (
         `pro != 0 ? `x
          : p2.sysfvar[.fX] - p1.sysfvar[.fX] + (float)p2.facing * (
            (p1.facing < 0) ^ (p2.facing < 0) ? p2.frontw : -p2.backw));
      index tmp;
      ^&.Explod e = `by.newExplod(tmp=);
      if(#e == 0) ret;
      e~ani = ani;
      e~postype = 0;
      e~offsetx =
        x - `hit.sparkx * (`pro != 0 ? -(float)(`pro*p1.facing) : 1.0);
      e~offsety =
        `y + `hit.sparky + (`by.id == p1.id ? 0.0 : p1.stVal.hit.sparky);
      e~relativef = 1;
      e~scalex = e~scaley = 1.0;
      e~ontop = 1;
      e~sprpriority = .consts.int_t::MIN;
      e~ownpal = 1;
      e~supermovetime = e~pausemovetime = -1;
      p1.setPos!e<>.self?(e<>=, e~postype, e~offsetx, e~offsety, e~relativef);
      `by.insertExplod(tmp);
    }
    if(pro == 0 && by.stVal.typ == .StTy::L && hit.reversal_attr <= 0){
      by.stVal.hit.lhit = true;
      ret false;
    }
    if(
      (
        `pyr.cs1tmp && `pyr.stVal.playerno != hit.player
        && (`pyr.ls(.lsGETHIT) ? hit.p2stateno >= 0 : `pyr.acttmp > 0))
      || (
        hit.p1stateno >= 0 && (
          by.ls(.lsGETHIT)
          || (by.cs1tmp && by.stVal.playerno != hit.player)))) ret false;
    bool guard =
      (pro != 0 || !by.ls(.lsUNGUARDABLE)) && `pyr.sf(.sfGUARD)
      && (!`pyr.ls(.lsGETHIT) || `pyr.stVal.hb.guarded);
    if(
      guard && .com.autoguard[`pyr.playerno]
      && `pyr.acttmp > 0 && !`pyr.ls(.lsGETHIT)
      && (`pyr.stVal.typ == .StTy::S || `pyr.stVal.typ == .StTy::C)
      && ((int)`pyr.stVal.typ&hit.guardflag) == 0) branch
    {
    cond ((int).StTy::S&hit.guardflag) != 0 && !`pyr.ls(.lsNOSTANDGUARD):
      `pyr.stVal.typ = .StTy::S;
    cond ((int).StTy::C&hit.guardflag) != 0 && !`pyr.ls(.lsNOCROUCHGUARD):
      `pyr.stVal.typ = .StTy::C;
    }
    hitting = `pyr.stVal.hitCheck(hit=, guard);
    bool p2s = false;
    {
      if(!`pyr.cs1tmp || !`pyr.ls(.lsGETHIT)) loop{
        index i = 0;
        while;
      do:
        if(
          `pyr.stVal.ho[i].time != 0
          && (
            `pyr.stVal.ho[i].attr & (
              pro != 0 ? hit.attr & 63 : (int)by.stVal.typ)) != 0
          && (`pyr.stVal.ho[i].attr & hit.attr & !63) != 0)
        {
          if(
            pro == 0 && #hitting == 1
            && (hit.p2stateno >= 0 || hit.p1stateno >= 0))
          {
            ret false;
          }
          if(`pyr.stVal.ho[i].stateno >= 0){
            `pyr.ho = i;
            break, break, break, break;
          }
        }
        i++;
      while i < #`pyr.stVal.ho:}
      if(#hitting == 1 && hit.p2stateno >= 0){
        if(
          `pyr.changeState1(
            hit.p2getp1state != 0 ? hit.player : `pyr.playerno, hit.p2stateno))
        {
          `pyr.setCtrl(false);
          p2s = true;
          `pyr.ho = -1;
        }
      }
    }
    by.targetsOfHit .= `pyr.id;
    bool hbset = !`pyr.cs1tmp || p2s || !`pyr.ls(.lsGETHIT);
    if(hbset){
      if(pro == 0) by.sprpriority = hit.p1sprpriority;
      `pyr.sprpriority = hit.p2sprpriority;
      `pyr.stVal.hb.hitid = hit.id;
      `pyr.stVal.hb.player = hit.player;
    }
    int numHits = hits;
    if((#hitting == 1 ? hit.pausetime : hit.guard_pausetime) > 0){
      numHits = 1;
    }
    if(hitting > 0){
      if(hitting == 1 && #`pyr.sounds > 0) `pyr.sounds[0].sound.new(0);
      if(`pyr.sysivar[.iBINDTOID] == by.id) `pyr.setBindTime(0);
      int absdamage = 0;
      branch{
      cond hbset:
        `pyr.stVal.setHb(
          hit=, guard, `pyr.stVal.mov == .MovTy::H || `pyr.ls(.lsGETHIT),
          absdamage=);
        {
          int byf = pro != 0 ? pro : by.facing;
          if(pro == 0 && hitting == 1) branch{
          cond hit.p1getp2facing != 0:
            byf = `pyr.facing*(hit.p1getp2facing < 0 ? (int)-1 : 1);
          cond hit.p1facing < 0:
            byf *= -1;
          }
          float byx = by.sysfvar[.fX] + (float)(pro != 0) * x;
          float byy = by.sysfvar[.fY] + (float)(pro != 0) * y;
          float snapx = 0.0/0.0;
          float snapy = 0.0/0.0;
          if(!.m.isnan(hit.mindistx)) branch{
          cond byf < 0:
            if(`pyr.sysfvar[.fX] > (byx - hit.mindistx)){
              snapx = byx - hit.mindistx;
            }
          else:
            if(`pyr.sysfvar[.fX] < (byx + hit.mindistx)){
              snapx = byx + hit.mindistx;
            }
          }
          if(!.m.isnan(hit.maxdistx)) branch{
          cond byf < 0:
            if(`pyr.sysfvar[.fX] < (byx - hit.maxdistx)){
              snapx = byx - hit.maxdistx;
            }
          else:
            if(`pyr.sysfvar[.fX] > (byx + hit.maxdistx)){
              snapx = byx + hit.maxdistx;
            }
          }
          if(hitting == 1 || `pyr.stVal.typ == .StTy::A){
            if(
              !.m.isnan(hit.mindisty)
              && `pyr.sysfvar[.fY] < (byy + hit.mindisty))
            {
              snapy = byy + hit.mindisty;
            }
            if(
              !.m.isnan(hit.maxdisty)
              && `pyr.sysfvar[.fY] > (byy + hit.maxdisty))
            {
              snapy = byy + hit.maxdisty;
            }
          }
          if(!.m.isnan(snapx)) `pyr.stVal.hb.xoff += snapx - `pyr.sysfvar[.fX];
          if(!.m.isnan(snapy)) `pyr.stVal.hb.yoff += snapy - `pyr.sysfvar[.fY];
          if(hit.snapt != 0 && `pyr.ho < 0){
            `pyr.setBindToId(by=);
            `pyr.setBindTime(
              hit.snapt + (int)(hit.snapt > 0 && !by.isPaused()));
            `pyr.sysivar[.iBINDFACING] = 0;
            `pyr.sysfvar[.fBINDPOSX] =
              !.m.isnan(hit.snapx) ? hit.mindistx : 0.0/0.0;
            `pyr.sysfvar[.fBINDPOSY] =
              !.m.isnan(hit.snapy)
              && (hitting == 1 || `pyr.stVal.typ == .StTy::A)
              ? hit.mindisty : 0.0/0.0;
          }
        }
      else:
        absdamage = hitting == 1 ? hit.hitdamage : hit.guarddamage;
      }
      branch{
      cond .super > 0:
        `pyr.sysivar[.iSUPERMOVETIME] =
          .m.max!int?(
            `pyr.sysivar[.iSUPERMOVETIME], `pyr.stVal.hb.hitshaketime);
      cond .pause > 0:
        `pyr.sysivar[.iPAUSEMOVETIME] =
          .m.max!int?(
            `pyr.sysivar[.iPAUSEMOVETIME], `pyr.stVal.hb.hitshaketime);
      }
      if(!p2s && !`pyr.ls(.lsGETHIT)) `pyr.cs1tmp = false;
      `pyr.sysivar[.iSPECIALFLAG] |= .lsGETHIT;
      bool live = `pyr.sysivar[.iLIFE] > 0;
      bool kill = hitting == 1 ? hit.kill : hit.guard_kill;
      `pyr.stVal.hb.damage +=
        `pyr.getDamage(
          (double)absdamage, kill, false, by.attackmul*by.attackmult);
      if(hbset && `pyr.stVal.hb.damage >= `pyr.sysivar[.iLIFE]) branch{
      cond kill || !live:
        `pyr.stVal.hb.fallf = true;
        if((int)`pyr.stVal.hb.fall.animtype < (int).AnimTy::Back){
          `pyr.stVal.hb.fall.animtype = .AnimTy::Back;
        }
        branch{
        cond `pyr.stVal.typ == .StTy::A:
          if(`pyr.stVal.hb.xvel < 0.0) `pyr.stVal.hb.xvel -= 2.0;
          if(`pyr.stVal.hb.yvel <= 0.0){
            `pyr.stVal.hb.yvel -= 2.0;
            if(`pyr.stVal.hb.yvel > -3.0) `pyr.stVal.hb.yvel = -3.0;
          }
        else:
          if(`pyr.stVal.hb.yvel == 0.0) `pyr.stVal.hb.xvel *= 0.66;
          if(`pyr.stVal.hb.xvel < 0.0) `pyr.stVal.hb.xvel -= 2.5;
          if(`pyr.stVal.hb.yvel <= 0.0){
            `pyr.stVal.hb.yvel -= 2.0;
            if(`pyr.stVal.hb.yvel > -6.0) `pyr.stVal.hb.yvel = -6.0;
          }
        }
        `pyr.stVal.hb.damage = `pyr.sysivar[.iLIFE];
      else:
        `pyr.stVal.hb.damage = `pyr.sysivar[.iLIFE] - 1;
      }
    }
    branch{
      ^&.snd.Sound sou;
    cond<hit> #hitting == 1:
      if(hit.sparkno != .com.IERR) branch{
      cond hit.reversal_attr > 0:
        hitspark(`pyr=, by=, hit.sparkno);
      else:
        hitspark(by=, `pyr=, hit.sparkno);
      }
      branch{
        if(hit.hitsoundg == .com.IERR) break;
        sou = by.newChannel(-1, false);
        if(#sou == 0) break;
      cond hit.hitsoundg < 0:
        if(#.fight~fsn > 0){
          sou~sound = .fight~fsn~getSound(!hit.hitsoundg, hit.hitsoundn);
        }
      else:
        if(#.cgi[by.playerno].sn > 0){
          sou~sound =
            .cgi[by.playerno].sn~getSound(hit.hitsoundg, hit.hitsoundn);
        }
      comm:
        sou~chrx = `pyr.sysfvar[.fX...fX+1];
        sou~setDefaultParameter();
        if(hit.hitsoundg >= 0) sou~setVol(by.sysivar[.iVOLUME]);
      }
      if(hitting > 0){
        by.addPower(hit.hitgetpower);
        if(`pyr.player) `pyr.addPower(hit.hitgivepower);
      }
    else:
      if(hit.guard_sparkno != .com.IERR) branch{
      cond hit.reversal_attr > 0:
        hitspark(`pyr=, by=, hit.guard_sparkno);
      else:
        hitspark(by=, `pyr=, hit.guard_sparkno);
      }
      branch{
        if(hit.guardsoundg == .com.IERR) break;
        sou = by.newChannel(-1, false);
        if(#sou == 0) break;
      cond hit.guardsoundg < 0:
        if(#.fight~fsn > 0){
          sou~sound = .fight~fsn~getSound(!hit.guardsoundg, hit.guardsoundn);
        }
      else:
        if(#.cgi[by.playerno].sn > 0){
          sou~sound =
            .cgi[by.playerno].sn~getSound(hit.guardsoundg, hit.guardsoundn);
        }
      comm:
        sou~chrx = `pyr.sysfvar[.fX...fX+1];
        sou~setDefaultParameter();
        if(hit.guardsoundg >= 0) sou~setVol(by.sysivar[.iVOLUME]);
      }
      if(hitting > 0){
        by.addPower(hit.guardgetpower);
        if(`pyr.player) `pyr.addPower(hit.guardgivepower);
      }
    comm:
      if(!hbset) break;
      `pyr.p1facing = 0;
      if(`pyr.ho >= 0) break;
      if(pro == 0 && hit.hitonce > 0) by.trTargetDrop(-1, false);
      by.addTarget(`pyr.id);
      `pyr.stVal.hb.addByid(by.id, by.sysivar[.iAIRJUGGLE]);
    diff<hit>:
      branch{
        int byf;
      cond pro == 0:
        byf = by.facing;
        branch{
        cond hit.p1getp2facing != 0:
          byf = `pyr.facing*(hit.p1getp2facing < 0 ? (int)-1 : 1);
          if(by.facing != byf) by.p1facing = byf;
        cond hit.p1facing < 0:
          byf *= -1;
          by.p1facing = byf;
        }
      else:
        byf = pro;
      comm:
        `pyr.p1facing =
          byf * (
            hit.p2facing == 0 ? (int)0
            : hit.p2facing < 0 ? (int)1 : -1);
        if(`pyr.p1facing == `pyr.facing) `pyr.p1facing = 0;
      }
      if(hit.p1stateno >= 0 && by.changeState1(hit.player, hit.p1stateno)){
        by.setCtrl(false);
      }
      if(`pyr.isFall() && !by.ls(.lsNOJUGGLECHECK)){
        `pyr.stVal.hb.by[-1].juggle -=
          pro != 0 ? hit.air_juggle : by.stVal.juggle;
      }
      if(hit.palfx_time > 0 && #`pyr.palfx > 0){
        `pyr.palfx~clear2(1);
        `pyr.palfx~time = hit.palfx_time;
        `pyr.palfx~mulr = hit.palfx_mulr;
        `pyr.palfx~mulg = hit.palfx_mulg;
        `pyr.palfx~mulb = hit.palfx_mulb;
        `pyr.palfx~addr = hit.palfx_addr;
        `pyr.palfx~addg = hit.palfx_addg;
        `pyr.palfx~addb = hit.palfx_addb;
        `pyr.palfx~amplr = hit.palfx_amplr;
        `pyr.palfx~amplg = hit.palfx_amplg;
        `pyr.palfx~amplb = hit.palfx_amplb;
        `pyr.palfx~cycletime = hit.palfx_cycletime;
        `pyr.palfx~color =
          .m.max!float?(0.0)<, .m.min!float?(1.0)<,
          ((float)hit.palfx_color / 256.0);
        `pyr.palfx~invertall = hit.palfx_invertall;
      }
      if(hit.envshake_time > 0){
        .stage.envShake.time = hit.envshake_time;
        .stage.envShake.freq = (hit.envshake_freq / 180.0) * .m.PI;
        .stage.envShake.ampl = hit.envshake_ampl;
        .stage.envShake.phase = hit.envshake_phase;
        .stage.envShake.setDefPhase();
      }
      `pyr.getcombo += hit.numhits*numHits;
      if(
        hitting > 0 && pro == 0 && `pyr.ls(.lsSCREENBOUND) && (
          (
            by.facing < 0 && `pyr.sysfvar[.fX]
            <= `pxmi + ((float)(by.stMver0() != 1) + 1.0) * 2.0)
          || (
            by.facing > 0 && `pyr.sysfvar[.fX]
            >= `pxma - ((float)(by.stMver0() != 1) + 1.0) * 2.0))
        ) switch(`pyr.stVal.typ)
      {
      case .StTy::S, .StTy::C:
        by.veloff = hit.ground_cornerpush_veloff * (float)by.facing;
      case .StTy::A:
        by.veloff = hit.air_cornerpush_veloff * (float)by.facing;
      case .StTy::L:
        by.veloff = hit.down_cornerpush_veloff * (float)by.facing;
      }
    else:
      if(
        hitting > 0 && pro == 0 && `pyr.ls(.lsSCREENBOUND) && (
          (
            by.facing < 0 && `pyr.sysfvar[.fX]
            <= `pxmi + ((float)(by.stMver0() != 1) + 1.0) * 2.0)
          || (
            by.facing > 0 && `pyr.sysfvar[.fX]
            >= `pxma - ((float)(by.stMver0() != 1) + 1.0) * 2.0))
        ) switch(`pyr.stVal.typ)
      {
      case .StTy::S, .StTy::C:
        by.veloff = hit.guard_cornerpush_veloff * (float)by.facing;
      case .StTy::A:
        by.veloff = hit.airguard_cornerpush_veloff * (float)by.facing;
      }
    comm:
      if(
        (`pyr.facing < 0) == (
          (pro != 0 ? pro : (by.p1facing != 0 ? by.p1facing : by.facing)) < 0))
      {
        `pyr.stVal.hb.xvel *= -1.0;
        if(.m.inRange!int?(1, 2, `pyr.stVal.hb.groundtype)){
          `pyr.stVal.hb.groundtype -= `pyr.stVal.hb.groundtype*2 - 3;
        }
        if(.m.inRange!int?(1, 2, `pyr.stVal.hb.airtype)){
          `pyr.stVal.hb.airtype -= `pyr.stVal.hb.airtype*2 - 3;
        }
      }
    }
    ret true;
  }
  if(!pro) loop{
    *`top.self p = `top;
    branch{
    cond pyr.facing > 0:
      pxmi = .com.xmin + pyr.getEdge(pyr.bedge, true);
      pxma = .com.xmax - pyr.getEdge(pyr.fedge, true);
    else:
      pxmi = .com.xmin + pyr.getEdge(pyr.fedge, true);
      pxma = .com.xmax - pyr.getEdge(pyr.bedge, true);
    }
    pyr.inguarddist = false;
    pyr.sysivar[.iSPECIALFLAG] &= !.lsGETHIT;
    float pl, pr;
    int contact = 0;
    branch{
    cond pyr.facing > 0:
      pl = pyr.sysfvar[.fX] - pyr.backw;
      pr = pyr.sysfvar[.fX] + pyr.frontw;
    else:
      pl = pyr.sysfvar[.fX] - pyr.frontw;
      pr = pyr.sysfvar[.fX] + pyr.backw;
    }
    pyr.enemynClear();
    while;
  do:
    contact = 0;
    if(
      p~c~atktmp == 0 || p~c~id == pyr.id || (
        p~c~stVal.hit.affectteam != 0
        && ((pyr.playerno&1) != (p~c~playerno&1))
        != (p~c~stVal.hit.affectteam > 0))) continue;
    if(
      p~c~stVal.mov == .MovTy::A && .m.inRange!float?(
        0.0, p~c~attackdist, -pyr.distX(p~c<>=)*(float)p~c~facing))
    {
      pyr.inguarddist = true;
    }
    if(
      p~c~stVal.hit.hitonce >= 0 && !p~c~hasTargetOfHit(pyr.id)
      && (p~c~stVal.hit.reversal_attr <= 0 || !pyr.hasTargetOfHit(p~c~id))
      && (
        pyr.hittmp < 2
        || p~c~ls(.lsNOJUGGLECHECK)
        || pyr.stVal.hb.getJuggle(p~c~id, p~c~sysivar[.iAIRJUGGLE])
        >= p~c~stVal.juggle)
      && pyr.hittable(
        p~c~stVal.hit=, p~c<>=, p~c~stVal.typ, [bool(&.Hitdef h=){
          ret
            (p~c~atktmp >= 0 || !pyr.hasTarget(p~c~id))
            && p~c~attrCheck(h=, pyr.id, pyr.stVal.typ)&&p~c~hitCheck(pyr=);
        }]))
    {
      if(
        p~c~stVal.mov == .MovTy::A && .m.inRange!float?(
          0.0, (float)p~c~stVal.hit.guard_dist,
          -pyr.distX(p~c<>=)*(float)p~c~facing))
      {
        pyr.inguarddist = true;
      }
      if(p~c~stVal.hit.reversal_attr <= 0) contact = -1;
      if(pyr.hitCheck(p~c<>=)){
        if(contact < 0) contact = 1;
        branch{
          int h;
          if(!foo(h=, p~c<>=, p~c~stVal.hit=, 0.0, 0.0, 0, 1)) break;
          bool mvh = h > 0 || p~c~stVal.hit.reversal_attr > 0;
        cond #h == 1:
          if(mvh) p~c~stVal.mctyp = .MoveContact::Hit;
          if(p~c~stVal.hit.reversal_attr > 0){
            pyr.stVal.mctyp = .MoveContact::Reversed;
            pyr.stVal.mctime = -1;
            pyr.stVal.hitdefContact = 1;
            pyr.targetsOfHit .= p~c~id;
            if(pyr.hittmp == 0) pyr.hittmp = -1;
            if(!pyr.ls(.lsGETHIT)){
              pyr.sysivar[.iHITPAUSETIME] =
                .m.max!int?(
                  1, p~c~stVal.hit.shaketime + (int)(p~c~mver0() == 1));
            }
          }
          if(!p~c~ls(.lsGETHIT)){
            p~c~sysivar[.iHITPAUSETIME] =
              .m.max!int?(
                1, p~c~stVal.hit.pausetime + (int)(p~c~mver0() == 1));
          }
          p~c~sysivar[.iUNIQHITCOUNT]++;
        else:
          if(mvh) p~c~stVal.mctyp = .MoveContact::Guarded;
          if(!p~c~ls(.lsGETHIT)){
            p~c~sysivar[.iHITPAUSETIME] =
              .m.max!int?(
                1, p~c~stVal.hit.guard_pausetime + (int)(p~c~mver0() == 1));
          }
        comm:
          if(p~c~stVal.hit.hitonce > 0) p~c~stVal.hit.hitonce = -1;
          if(mvh) p~c~stVal.mctime = -1;
          p~c~stVal.hitdefContact = 1;
        }
      }
    }
  continue:
    if(
      (pyr.playerno&1) != (p~c~playerno&1)
      && pyr.ls(.lsPLAYERPUSH) && p~c~ls(.lsPLAYERPUSH) && (
        (
          pyr.stVal.typ == .StTy::A
          || pyr.sysfvar[.fY] - p~c~sysfvar[.fY] < pyr.getHeight())
        && (
          p~c~stVal.typ == .StTy::A
          || p~c~sysfvar[.fY] - pyr.sysfvar[.fY] < p~c~getHeight())))
    {
      float el, er;
      branch{
      cond p~c~facing > 0:
        el = p~c~sysfvar[.fX] - p~c~backw;
        er = p~c~sysfvar[.fX] + p~c~frontw;
      else:
        el = p~c~sysfvar[.fX] - p~c~frontw;
        er = p~c~sysfvar[.fX] + p~c~backw;
      }
      if(
        pl < er && el < pr
        && (contact > 0 || pyr.clsnCheck(p~c<>=, false, false)))
      {
        pyr.pushed = p~c~pushed = true;
        branch{
          float tmp = pyr.distX(p~c<>=);
          if(tmp == 0.0){
            tmp =
              (float)(
                pyr.sysfvar[.fY] > -p~c~sysfvar[.fY]
                ? pyr.facing : -p~c~facing);
          }
        cond tmp > 0.0:
          pyr.sysfvar[.fX] -= (pr - el) * 0.5;
          p~c~sysfvar[.fX] += (pr - el) * 0.5;
        else:
          pyr.sysfvar[.fX] += (er - pl) * 0.5;
          p~c~sysfvar[.fX] -= (er - pl) * 0.5;
        }
        if(pyr.ls(.lsSCREENBOUND)){
          .m.limRange!float?(pyr.sysfvar[.fX]=, pxmi, pxma);
        }
        if(p~c~ls(.lsSCREENBOUND)){
          float l, r;
          branch{
          cond p~c~facing > 0:
            l = .com.xmin + p~c~getEdge(p~c~bedge, true);
            r = .com.xmax - p~c~getEdge(p~c~fedge, true);
          else:
            l = .com.xmin + p~c~getEdge(p~c~fedge, true);
            r = .com.xmax - p~c~getEdge(p~c~bedge, true);
          }
          .m.limRange!float?(p~c~sysfvar[.fX]=, l, r);
        }
        .m.limRange!float?(
          pyr.sysfvar[.fX]=, (float).stg~leftbound, (float).stg~rightbound);
        .m.limRange!float?(
          p~c~sysfvar[.fX]=, (float).stg~leftbound, (float).stg~rightbound);
        pyr.drawX = pyr.sysfvar[.fX];
        p~c~drawX = p~c~sysfvar[.fX];
      }
    }
    p = p~next;
  while #p > 0:}
  if(pro) loop{
    index i = 0;
    while;
  do:
    if(pyr.playerno != i && #.chars[i] > 0){
      int orgatktmp = .chars[i]<>~atktmp;
      .chars[i]<>~atktmp = -1;
      .projs[i]:<-[void(proj=){
        if(
          proj.id < 0 || proj.hits < 0 || (
            proj.hit.affectteam != 0 && ((pyr.playerno&1) != (i&1))
            != (proj.hit.affectteam > 0))) ret;
        if(
          .m.inRange!float?(
            0.0, (float).chars[i]<>~sysivar[.iPROJ_ATTACK_DIST],
            (pyr.sysfvar[.fX] - proj.x) * (float)proj.facing))
        {
          pyr.inguarddist = true;
        }
        if(proj.hits == 0) ret;
        if(
          pyr.atktmp != 0
          && (
            pyr.stVal.hit.affectteam == 0 || (
            ((i&1) != (pyr.playerno&1)) == (pyr.stVal.hit.affectteam > 0)))
          && (pyr.stVal.hit.hitflag & (int).StTy::U) != 0
          && pyr.hitProjCheck(proj=))
        {
          proj.hits = -2;
          .cgi[i].pctyp = .ProjContact::Cancel;
          .cgi[i].pctime = 0;
          .cgi[i].pcid = proj.id;
          pyr.stVal.hitdefContact = 1;
          ret;
        }
        if(
          !(pyr.cs1tmp && (pyr.ls(.lsGETHIT) || pyr.acttmp > 0))
          && (
            .chars[i]<>~ls(.lsNOJUGGLECHECK)
            || pyr.stVal.hb.getJuggle(
              .chars[i]<>~id, .chars[i]<>~sysivar[.iAIRJUGGLE])
            >= proj.hit.air_juggle)
          && proj.timemiss <= 0
          && proj.hitpause <= 0 && pyr.hittable(
            proj.hit=, .chars[i]<><>=, .StTy::N,
            [bool(&.Hitdef h=){ret false;}]))
        {
          int oldhittmp = pyr.hittmp;
          if(pyr.ls(.lsGETHIT)) pyr.hittmp = (int)pyr.isFall() + 1;
          if(
            .m.inRange!float?(
              0.0, (float)proj.hit.guard_dist,
              -pyr.distX(.chars[i]<><>=) * (float).chars[i]<>~facing))
          {
            pyr.inguarddist = true;
          }
          if(pyr.projHitCheck(proj=)){
            int hit;
            if(
              foo(
                hit=, .chars[i]<><>=, proj.hit=,
                proj.x - .chars[i]<>~sysfvar[.fX],
                proj.y - .chars[i]<>~sysfvar[.fY],
                proj.facing, proj.misstime <= 0 ? proj.hits : 1))
            {
              proj.timemiss = !.m.max!int?(0, proj.misstime);
              branch{
              cond #hit == 1:
                .cgi[i].pctyp = .ProjContact::Hit;
                .cgi[i].pctime = 0;
                .cgi[i].pcid = proj.id;
                proj.hitpause = .m.max!int?(0, proj.hit.pausetime);
              else:
                .cgi[i].pctyp = .ProjContact::Guarded;
                .cgi[i].pctime = 0;
                .cgi[i].pcid = proj.id;
                proj.hitpause = .m.max!int?(0, proj.hit.guard_pausetime);
              }
            }
          }
        break:
          pyr.hittmp = oldhittmp;
        }
      }];
      .chars[i]<>~atktmp = orgatktmp;
    }
    i++;
  while i < #.projs:}
}
public void PlayerList!&Char?::getHit()
{
  *`top.self p;
  loop{p = `top; while; do:
    `clsn(p~c<>=, false);
    p = p~next;
  while #p > 0:}
  loop{p = `top; while; do:
    `clsn(p~c<>=, true);
    p = p~next;
  while #p > 0:}
}
public void PlayerList!&Char?::tick()
{
  .com.gametime++;
  .cgi:<-[void(gi=){if(gi.unhittable > 0) gi.unhittable--;}];
  loop{
    *`top.self p = `top;
    while;
  do:
    p~c~tick();
    p = p~next;
  while #p > 0:}
}

void playSound()
{
  if(.sdl.setSndBuf(.snd.sndbuf)){
    .snd.sndbufClear();
    .snd.mixSounds();
    .chars:<-:<-[void(c){
      if(#c > 0) c~sounds:<-[void(s=){
        s.mix(
          .snd.sndbuf,
          .com.xmin - .com.screenleft, .com.xmax + .com.screenright);
      }];
    }];
  }
}
void stopAllSound()
{
  .chars:<-:<-[void(c){
    if(#c > 0) c~sounds:<-[void(s=){s.sound.new(0);}];
  }];
}

public void charInit(&.Char c=, int no, int idx)
{
  c.clearVal();
  c.playerno = no;
  c.helperindex = idx;
  if(c.helperindex == 0){
    c.keyctrl = true;
    c.player = true;
  }
  c.key = .m.inRange!int?(0, #.com.com-1, no) && .com.com[no] == 0 ?  no : !no;
}

public ^&Char create(int no)
{
  index idx = 0;
  loop{while; do:
    if(.chars[no][idx]~helperindex < 0) break;
    idx++;
  while idx < #.chars[no]:
    if(idx >= .cfg.HelperMax) ret .consts.null!&.Char?();
    .chars[no].new[idx].new(1);
  }
  ^&.Char c = .chars[no][idx];
  .charInit(c<>=, no, idx);
  c~id = .id++;
  .players.add(c);
  ret c;
}

^&.fgt.LifePower getLifePower()
{
  %&.fgt.LifePower lpl;
  .chars:<-[void(c){
    branch{
    cond #c > 0:
      lpl.new[-1].set(
        (float)c<>~sysivar[.iLIFE] / (float)c<>~sysivar[.iLIFEMAX],
        (float)c<>~getSharePower() / (float)c<>~sysivar[.iPOWERMAX],
        c<>~getSharePower() / 1000);
    else:
      lpl.new[-1].set(0.0, 0.0, 0);
    }
  }];
  ret lpl;
}

void update(
  float cvmin=, float cvmax=,
  float highest=, float lowest=, float leftest=, float rightest=)
{
  .players.update(cvmin=, cvmax=, highest=, lowest=, leftest=, rightest=);
  loop{index i = 0; while; do:
    .projs[i]:<-[void(p=){if(p.id >= 0) p.update(i);}];
    i++;
  while i < #.projs:}
  if(.com.tickNextFrame()){
    loop{index i = 0; while; do:
      .projs[i]:<-[void(p=){if(p.id >= 0) p.projClsn(i);}];
      i++;
    while i < #.projs:}
    .players.getHit();
    loop{index i = 0; while; do:
      .projs[i]:<-[void(p=){if(p.id != .com.IERR) p.tick(i);}];
      i++;
    while i < #.projs:}
    .players.tick();
  }
}

void commandUpdate()
{
  loop{index i = 0; while; do:
    if(#.chars[i] == 0) continue;
    .chars[i].[void(p){
      p<>~[void(r=){
        bool act =
          .super > 0 ? r.sysivar[.iSUPERMOVETIME] != 0
          : .pause <= 0 || r.sysivar[.iPAUSEMOVETIME] != 0;
        if(
          act && !r.ls(.lsNOAUTOTURN)
          && (r.stVal.no == 0 || r.stVal.no == 11 || r.stVal.no == 20))
        {
          r.furimuki();
        }
        p:<-:<-[void(c=){
          if(
            (c.helperindex == 0 || c.helperindex > 0 && c.cmd != r.cmd)
            && c.cmd~input(c.key, c.facing)) loop
          {
            index i = 0;
            bool hp = c.isHitPaused();
            int buftime = (int)(hp && c.mver0() != 1);
            branch{
            cond .super > 0:
              if(!act && .super <= .superendcmdbuftime) hp = true;
            cond .pause > 0:
              if(!act && .pause <= .pauseendcmdbuftime) hp = true;
            }
            while;
          do:
            c.cmd[i].step(c.facing, c.key < 0, hp, buftime + (int)hp);
            i++;
          while i < #c.cmd:}
        }];
        if(r.key < 0){
          index cc =
            r.roundState() == 2 && .m.rand(0, .com.com[i]+16) > 16
            ? .m.rand(0, #r.cmd[r.stVal.playerno].commands-1) : -1;
          p:<-:<-[void(c=){if(c.helperindex >= 0) c.cpucmd = cc;}];
        }
      }];
    }];
  continue:
    i++;
  while i < #.chars:}
}

void anim()
{
  loop{index i = 0; while; do:
    loop{index j = 0; while; do:
      if(.projs[i][j].id >= 0) .projs[i][j].anime(.cgi[i].mver0 != 1, i);
      j++;
    while j < #.projs[i]:}
    i++;
  while i < #.projs:}
  loop{index i = 0; while; do:
    if(#.players.drawOrder[i] > 0) .players.drawOrder[i]~drawAnim();
    i++;
  while i < #.players.drawOrder:}
}

public float action(
  float x=, float y=, float leftest=, float rightest=, float scl)
{
  .anims.new(0);
  .topanims.new(0);
  .shadows.new(0);
  .resetDrawnClsnList();
  .com.cam.update!.stg<>.self?(scl, x, y, .stg<>=);
  float cvmin = 0.0, cvmax = 0.0;
  float highest = 0.0;
  float lowest = .com.cam.stg.verticalfollow > 0.0 ? .com.cam.screenY : 0.0;
  rightest = leftest = x;
  int rs4t = -(.fight~ro.over_hittime + .fight~ro.over_waittime);
  bool introSkip = false;
  branch{
  cond .com.tickFrame():
    .com.xmin =
      .com.cam.screenX + .com.cam.xOffset + .com.screenleft;
    .com.xmax =
      .com.cam.screenX + .com.cam.xOffset
      + ((float).com.GameWidth / .com.cam.scale) - .com.screenright;
    if(.com.xmin > .com.xmax){
      .com.xmin = .com.xmax = (.com.xmin + .com.xmax) * 0.5;
    }
    .sff.allPalFX~step();
    .stage.bgPalFX~step();
    .stage.envShake.next();
    if(.envcol_time > 0) .envcol_time--;
    .com.drawscale = 0.0/0.0;
    .com.zoomposx = 0.0;
    .com.zoomposy = 0.0;
    branch{
    cond .super > 0:
      .super--;
    cond .pause > 0:
      .pause--;
    }
    if(.pausetime < 0){
      .pausetime = !.pausetime;
      .pause = .pausetime;
    }
    if(.supertime < 0){
      .supertime = !.supertime;
      .super = .supertime;
    }
    branch{
    cond .super <= 0 && .pause <= 0:
      .specialFlag = 0d0;
    else:
      .specialFlag &= !.gsROUNDNOTOVER;
    }
    if(#.superanim > 0) .superanim~ani.action();
    .players.action(x, cvmin=, cvmax=, highest=, lowest=, leftest=, rightest=);
  else:
    .update(cvmin=, cvmax=, highest=, lowest=, leftest=, rightest=);
  }
  %bool hbuf;
  .chars:<-[void(c){
    branch{
    cond #c > 0:
      hbuf .=
        (c<>~getcombo != 0 || c<>~stVal.mov == .MovTy::H) && !c<>~sf(.sfOVER);
    else:
      hbuf .= false;
    }
  }];
  ^int cb.new(2);
  cb[0] = cb[1] = 0;
  loop{index i = 0; while; do:
    .chars[i]:<-[void(c){
      cb[!i&1] = .m.min!int?(999)<, .m.max!int?(cb[!i&1], c~getcombo);
    }];
    i++;
  while i < #.chars:}
  .fight~step(.com.tmode, .getLifePower(), hbuf, cb);
  void sprite()
  {
    if(#.superanim > 0){
      .addAnimList(
        .topanims=, .superanim, 5, .superposx, .superposy, false,
        (float).superfacing, 1.0, 0.0, .cgi[.superplayer].mver0 != 1,
        1.0, 1.0, -1, 0, true, .superpmap, 0, 0, 0.0, 0.0);
      if(.superanim~ani.loopend) .superanim.new(0);
    }
    .anim();
    void expUpdate(^%index drawlist=, bool delI)
    {
      loop{index i = 0; while; do:
        loop{index j = #drawlist[i]-1; while; do:
          if(drawlist[i][j] < 0) continue;
          .explods[i][drawlist[i][j]].update(.cgi[i].mver0 != 1, i);
          if(.explods[i][drawlist[i][j]].id == .com.IERR) branch{
          cond delI:
            .delIL(drawlist[i]=, j);
          else:
            drawlist[i][j] = -1;
          }
        continue:
          j--;
        while j >= 0:}
        i++;
      while i < #.explods:}
    }
    expUpdate(.expdrawlist=, true);
    expUpdate(.topexpdrawlist=, false);
  }
  sprite();
  leftest -= x;
  rightest -= x;
  float tmp = .com.cam.action!.fight<>.self?(
    x=, y=, leftest, rightest, lowest, highest,
    cvmin, cvmax, .fight<>=, .super > 0 || .pause > 0);
  void addWinCount(bool p1, bool p2)
  {
    branch{
    cond
      .com.tmode[0] != (int).com.TeamMode::Turns
      && .com.tmode[1] != (int).com.TeamMode::Turns
      && .com.draws < .fight~ro.match_maxdrawgames && p1 && p2
      :
    else:
      if(p2) .com.p1wins += 1;
      if(p1) .com.p2wins += 1;
    }
  }
  void setWinType(bool p1, bool p2)
  {
    branch{
    cond
      .com.tmode[0] != (int).com.TeamMode::Turns
      && .com.tmode[1] != (int).com.TeamMode::Turns
      && .com.draws < .fight~ro.match_maxdrawgames && p1 && p2
      :
      .com.draws++;
    else:
      if(p2) .fight~wi[0].add(.winty[0]);
      if(p1) .fight~wi[1].add(.winty[1]);
    }
  }
  bool finish()
  {
    if(.com.intro > 0) ret false;
    bool p1 = false, p2 = false;
    loop{index i = 0; while; do:
      if(#.chars[i] > 0 && !.chars[i][0]~isKO()) break;
      i += 2;
    while i < #.chars:
      p1 = true;
      loop{index i = 1; while; do:
        if(
          #.chars[i] > 0
          && .chars[i][0]~sysivar[.iLIFE]
          < .chars[i][0]~sysivar[.iLIFEMAX]) break;
        i += 2;
      while i < #.chars:
        .fgt.setPerfect(.winty[1]=);
      }
    }
    loop{index i = 1; while; do:
      if(#.chars[i] > 0 && !.chars[i][0]~isKO()) break;
      i += 2;
    while i < #.chars:
      p2 = true;
      loop{index i = 0; while; do:
        if(
          #.chars[i] > 0
          && .chars[i][0]~sysivar[.iLIFE]
          < .chars[i][0]~sysivar[.iLIFEMAX]) break;
        i += 2;
      while i < #.chars:
        .fgt.setPerfect(.winty[0]=);
      }
    }
    if(.com.time == 0){
      .com.intro = -.fight~ro.over_hittime;
      if(!(p1 || p2)) .winty[0] = .winty[1] = .fgt.WinTy::T;
    }
    if(.com.intro == -.fight~ro.over_hittime && (p1 || p2)){
      branch{
      cond p1 && p2:
        .ko = .fgt.KOTy::DKO;
        .com.win = -1;
      cond p1:
        .ko = .fgt.KOTy::KO;
        .com.win = 1;
      cond p2:
        .ko = .fgt.KOTy::KO;
        .com.win = 0;
      }
    }
    ret p1 || p2 || .com.time == 0;
  }
  void posreset()
  {
    loop{index i = 0; while; do:
      if(#.chars[i] > 0) .chars[i][0]~posReset();
      i++;
    while i < #.chars:}
  }
  if(.com.tickNextFrame()) branch{
  cond .fight~ro.cur < 1:
    if(
      (
        .shuttertime > 0
        || .cmd.anybutton() && .com.intro > .fight~ro.ctrl_time)
      && ++.shuttertime == 15)
    {
      .resetGblEffect();
      .com.intro = .fight~ro.ctrl_time;
      loop{index i = 0; while; do:
        if(#.chars[i] > 0){
          .charClear(i);
          .chars[i][0]~trSelfState(0, -1, 0);
        }
        i++;
      while i < #.chars:}
      float ox = x;
      x = 0.0;
      leftest =
        .m.max!float?(
          (float).m.min!int?(.stg~p1.startx, .stg~p2.startx) * .stg~localscl,
          -(.com.CharGameWidth / 2.0) / .com.cam.baseScale() + .com.screenleft)
        - ox;
      rightest =
        .m.min!float?(
          (float).m.max!int?(.stg~p1.startx, .stg~p2.startx) * .stg~localscl,
          (.com.CharGameWidth / 2.0) / .com.cam.baseScale() - .com.screenright)
        - ox;
      introSkip = true;
      .fight~ro.callFight();
    }
  else:
    if(.shuttertime > 0) .shuttertime--;
  }
  if(.fight~ro.act(.ko)){
    branch{
    cond .com.intro > .fight~ro.ctrl_time:
      .com.intro--;
      if(.gs(.gsINTRO) && .com.intro <= .fight~ro.ctrl_time){
        .com.intro = .fight~ro.ctrl_time + 1;
      }
    cond .com.intro > 0:
      if(.com.intro == .fight~ro.ctrl_time) posreset();
      .com.intro--;
      if(.com.intro == 0) loop{index i = 0; while; do:
        if(#.chars[i] > 0) branch{
          .chars[i]<>~sysivar[.iSYSFLAG] &= !.sfOVER;
        cond .chars[i]<>~stVal.no == 0:
          .chars[i]<>~setCtrl(true);
        cond .chars[i]<>~isAlive():
          .chars[i]<>~trSelfState(0, -1, 1);
        }
        i++;
      while i < #.chars:}
    }
    if(
      .com.intro == 0 && .com.time > 0 && !.gs(.gsTIMERFREEZE)
      && (.super <= 0 || .superpausebg == 0) 
      && (.pause <= 0 || .pausebg == 0)) .com.time--;
    branch{
    cond .roundEnd() || finish():
      if(.com.intro == -.fight~ro.over_hittime && .ko != .fgt.KOTy::NotYet){
        addWinCount(!.chars[0]<>~isWin(), !.chars[1]<>~isWin());
      }
      if(
        .winskipped || !.gs(.gsROUNDNOTOVER)
        || .com.intro >= rs4t - .fight~ro.over_wintime)
      {
        .com.intro--;
        if(.com.intro == rs4t-1) loop{
          if(.com.time == 0) .com.intro -= .fight~ro.over_wintime;
          if(.waitdown <= 0) break;
          index i = 0;
          while;
        do:
          if(#.chars[i] > 0 && !.chars[i][0]~isOver()) .com.intro = rs4t;
          i++;
        while i < #.chars:}
        if(.waitdown <= 0 || .com.intro < rs4t - .fight~ro.over_wintime) loop{
          index i = 0;
          if(.waitdown >= 0){
            if(.ko == .fgt.KOTy::NotYet){
              bool p1 = false, p2 = false;
              float l1 = 0.0, l2 = 0.0;
              loop{index i = 0; while; do:
                if(#.chars[i] > 0){
                  l1 +=
                    (
                      .com.tmode[0] == (int).com.TeamMode::Simul
                      ? 1.0 / (float).com.numSimul[0] : 1.0)
                    * (float).chars[i][0]~sysivar[.iLIFE]
                    / (float).chars[i][0]~sysivar[.iLIFEMAX];
                }
                i += 2;
              while i < #.chars:}
              loop{index i = 1; while; do:
                if(#.chars[i] > 0){
                  l2 +=
                    (
                      .com.tmode[1] == (int).com.TeamMode::Simul
                      ? 1.0 / (float).com.numSimul[1] : 1.0)
                    * (float).chars[i][0]~sysivar[.iLIFE]
                    / (float).chars[i][0]~sysivar[.iLIFEMAX];
                }
                i += 2;
              while i < #.chars:}
              branch{
              cond l1 > l2:
                p2 = true;
              cond l2 > l1:
                p1 = true;
              else:
                p1 = p2 = true;
              }
              if(p1) loop{index i = 1; while; do:
                if(
                  #.chars[i] > 0
                  && .chars[i][0]~sysivar[.iLIFE]
                  < .chars[i][0]~sysivar[.iLIFEMAX]) break;
                i += 2;
              while i < #.chars:
                .fgt.setPerfect(.winty[1]=);
              }
              if(p2) loop{index i = 0; while; do:
                if(
                  #.chars[i] > 0
                  && .chars[i][0]~sysivar[.iLIFE]
                  < .chars[i][0]~sysivar[.iLIFEMAX]) break;
                i += 2;
              while i < #.chars:
                .fgt.setPerfect(.winty[0]=);
              }
              branch{
              cond p1 && p2:
                .ko = .fgt.KOTy::TODraw;
                .com.win = -1;
              cond p1:
                .ko = .fgt.KOTy::TO;
                .com.win = 1;
              cond p2:
                .ko = .fgt.KOTy::TO;
                .com.win = 0;
              }
              addWinCount(!.chars[0]<>~isWin(), !.chars[1]<>~isWin());
            }
            setWinType(!.chars[0]<>~isWin(), !.chars[1]<>~isWin());
          }
          while;
        do:
          if(#.chars[i] == 0) continue;
          .chars[i][0]~[void(c=){
            if(
              .waitdown >= 0 && .com.time > 0 && c.isWin() && !c.isKO()
              && !.com.matchOver() && (
                .com.tmode[0] == (int).com.TeamMode::Turns
                || .com.tmode[1] == (int).com.TeamMode::Turns))
            {
              c.sysivar[.iLIFE] +=
                (int)(
                  (float)c.sysivar[.iLIFEMAX]
                  * (float).com.time * (1.0/60.0) * .com.turnsRecoveryRate);
              .m.limMax!int?(c.sysivar[.iLIFE]=, c.sysivar[.iLIFEMAX]);
            }
            if(!c.sf(.sfOVER) && !c.isHitPaused() && !c.isKO()){
              c.sysivar[.iSYSFLAG] |= .sfOVER;
              c.trSelfState(c.isWin() ? 180 : (c.isLose() ? 170 : 175), -1, 1);
            }
          }];
        continue:
          i++;
        while i < #.chars:
          .waitdown = 0;
        }
        .waitdown--;
      }
    cond .com.intro < 0:
      .com.intro = 0;
    }
  }
  if(.com.turbo == 0.0 || .com.tickNextFrame()) branch{
    int slowt = -(.fight~ro.over_hittime+((.fight~ro.slow_time+3)>>2));
    float spd = .com.pause && !.com.step ? 0.0 : .com.Speed*.com.accel;
    int slowfade = .fight~ro.slow_time * 2 / 5;
    if(.gs(.gsNOKOSLOW) || .com.time == 0) else;
  cond .m.inRange!int?(slowt, -.fight~ro.over_hittime-1, .com.intro):
    .com.turbo = spd * 0.25;
  cond .m.inRange!int?(slowt-slowfade, slowt-1, .com.intro):
    .com.turbo =
      spd*(0.25 + 0.75 * (float)(-.com.intro + slowt)/(float)slowfade);
  else:
    .com.turbo = spd;
  }
  .sdl.pauseBGM(.gs(.gsNOMUSIC));
  .playSound();
  if(introSkip) tmp = 1.0 / scl;
  leftest = (leftest - .com.screenleft) * .com.cam.baseScale();
  rightest = (rightest + .com.screenright) * .com.cam.baseScale();
  ret tmp;
}
public void draw(float x, float y, float scl)
{
  ^&.fgt.LifePower lpl = .getLifePower();
  uint ecol =
    ((uint).envcol_b&0xff)
    | ((uint).envcol_g&0xff)<<0d8 | ((uint).envcol_r&0xff)<<0d16;
  ^ubyte px;
  px.new(1);
  px<> = 0d0;
  %^/char winner;
  if(.com.win >= 0){
    winner.new[-1] = .cgi[.com.win].displayname;
    if(.com.tmode[.com.win] == (int).com.TeamMode::Simul){
      winner.new[-1] = .cgi[.com.win+2].displayname;
    }
  }
  ^^/char names.new(#.chars);
  ^^&.com.PalFX facefx.new(#.chars);
  loop{index i = 0; while; do:
    if(#.chars[i] > 0 && i < #.fight~fa[.com.tmode[i&1]]){
      names[i] = .cgi[i].displayname;
      facefx[i] = .chars[i][0]~getPalfx();
      .fight~fa[.com.tmode[i&1]][i].face_spr.[void(fs){
        if(#fs == 0) ret;
        .cgi[i].sf~palList.swapPalMap(facefx[i]~remap=);
        fs~colorPallet.new(0);
        fs~colorPallet = fs~getPal(.cgi[i].sf~palList=);
        .cgi[i].sf~palList.swapPalMap(facefx[i]~remap=);
      }];
    }
    i++;
  while i < #names:}
  int ob = .com.brightness;
  .com.brightness = 256 >> (int)(.super > 0 && .superdarken != 0);
  float bgx = x / .stg~localscl, bgy = y / .stg~localscl;
  if(.envcol_time == 0) branch{
  cond .gs(.gsNOBG):
    {
      uint c = 0x0;
      if(.sff.allPalFX~enable){
        int r = 0, g = 0, b = 0;
        if(.sff.allPalFX~einvertall != 0) r = g = b = 255;
        r = (r + .sff.allPalFX~eaddr)*.sff.allPalFX~emulr >> 8;
        g = (g + .sff.allPalFX~eaddg)*.sff.allPalFX~emulg >> 8;
        b = (b + .sff.allPalFX~eaddb)*.sff.allPalFX~emulb >> 8;
        .m.limRange!int?(r=, 0, 255);
        .m.limRange!int?(g=, 0, 255);
        .m.limRange!int?(b=, 0, 255);
        c = (uint)(r << 16 | g << 8 | b); 
      }
      .com.screenFill(c);
    }
  else:
    if(.stg~debugbg) .com.screenFill(0x00ff00ff);
    .stg~bgDraw(false, bgx, bgy, scl);
  comm:
    if(!.gs(.gsGLOBALNOSHADOW)){
      if(.stg~reflection > 0) .drawReflection(x, y, scl*.com.cam.baseScale());
      .drawShadowList(x, y, scl * .com.cam.baseScale());
    }
    {
      float off = .stage.envShake.getOffset();
      float yofs =
        (
          scl > 1.0 && .com.cam.stg.verticalfollow > 0.0
          ? (.com.cam.screenZoff + (float)(.com.GameHeight - 240))
          : (float).com.GameHeight)
        * (1.0/scl - 1.0);
      float yofs2 =
        scl > 1.0 && .com.cam.stg.verticalfollow > 0.0
        ? (240.0 - .com.cam.screenZoff)*(1.0 - 1.0/scl) : 0.0;
      *.com.scrrect.self rect = .com.scrrect;
      if(off < (yofs - y + .com.cam.boundH)*scl){
        rect.h =
          (
            (int).m.ceil(
              ((yofs - y + .com.cam.boundH)*scl - off) * (float).com.scrrect.h)
            + (.com.GameHeight-1))
          / .com.GameHeight;
        fade(rect=, 255);
      }
      if(off > (-y + yofs2)*scl){
        rect.h =
          (
            (int).m.ceil(((y - yofs2)*scl + off) * (float).com.scrrect.h)
            + (.com.GameHeight-1))
          / .com.GameHeight;
        rect.y = (int)(.com.scrrect.h - rect.h);
        fade(rect=, 255);
      }
      float bl = .m.min!float?(x, .com.cam.boundL);
      float br = .m.max!float?(x, .com.cam.boundR);
      float xofs = (float).com.GameWidth*(1.0/scl - 1.0) / 2.0;
      rect = .com.scrrect;
      if(x - xofs < bl){
        rect.w =
          (
            (int).m.ceil((bl - (x - xofs))*scl * (float).com.scrrect.w)
            + (.com.GameWidth-1))
          / .com.GameWidth;
        fade(rect=, 255);
      }
      if(x + xofs > br){
        rect.w =
          (
            (int).m.ceil(((x + xofs) - br)*scl * (float).com.scrrect.w)
            + (.com.GameWidth-1))
          / .com.GameWidth;
        rect.x = (int)(.com.scrrect.w - rect.w);
        fade(rect=, 255);
      }
    }
    .fight~draw(0, lpl, names, .gs(.gsNOBARDISPLAY), facefx, .superplayer);
    .fight~ro.draw(0, .ko, winner);
  }
  if(.envcol_time != 0) .com.screenFill(ecol);
  if(.envcol_time == 0 || .envcol_under != 0){
    .drawAnimList(.anims=, x, y, scl*.com.cam.baseScale());
    if(.envcol_time == 0 && !.gs(.gsNOFG)) .stg~bgDraw(true, bgx, bgy, scl);
  }
  .fight~draw(1, lpl, names, .gs(.gsNOBARDISPLAY), facefx, .superplayer);
  .fight~ro.draw(1, .ko, winner);
  .drawAnimList(.topanims=, x, y, scl*.com.cam.baseScale());
  .fight~draw(2, lpl, names, .gs(.gsNOBARDISPLAY), facefx, .superplayer);
  .fight~ro.draw(2, .ko, winner);
  void fade(.com.scrrect.self rect=, int alpha)
  {
    .com.rectFill(
      rect=, 0x000000, (alpha>>(int).com.clsndraw)+(int).com.clsndraw*128);
  }
  branch{
    int tmp =
      .fight~ro.over_hittime + .fight~ro.over_waittime
      + (.fight~ro.over_time - .fight~ro.start_waittime);
  cond .com.intro > .fight~ro.ctrl_time+1:
    fade(
      .com.scrrect=,
      256 * (.com.intro - (.fight~ro.ctrl_time+1)) / .fight~ro.start_waittime);
  cond .fight~ro.over_time >= .fight~ro.start_waittime && .com.intro < -tmp:
    fade(.com.scrrect=, 256 * (-tmp - .com.intro) / .fight~ro.start_waittime);
  cond .com.clsndraw:
    fade(.com.scrrect=, 0);
  }
  if(.shuttertime > 0){
    *.com.scrrect.self rect = .com.scrrect;
    rect.h = .shuttertime * ((.com.scrrect.h+1)>>1) / 15;
    fade(rect=, 255);
    rect.y = .com.scrrect.h - rect.h;
    fade(rect=, 255);
  }
  .com.brightness = ob;
  if(.com.clsndraw) .drawClsn();
}

void resetGblEffect()
{
  .sff.allPalFX~clear();
  .stage.bgPalFX~clear();
  .stage.envShake.clear();
  .pause = 0;
  .pausetime = 0;
  .super = 0;
  .supertime = 0;
  .superanim.new(0);
  .envcol_time = 0;
  .specialFlag = 0d0;
}
void resetGbl()
{
  .resetGblEffect();
  .fight~reset();
  .ko = .fgt.KOTy::NotYet;
  .com.win = -1;
  .winty[0] = .winty[1] = .fgt.WinTy::N;
  .com.cam.resetZoomdelay();
  .playerid.new(0);
  .waitdown = .fight~ro.over_hittime + .fight~ro.over_waittime + 900;
  .shuttertime = 0;
  .winskipped = false;
}

void charClear(int pn)
{
  .chars[pn].[void(cs){
    loop{index j = 1; while; do:
      cs[j]~destroySelf();
      cs[j]~sounds.new(0);
      j++;
    while j < #.chars[pn]:}
    .projs[pn].new(0);
    .explods[pn].new(0);
    .expdrawlist[pn].new(0);
    .topexpdrawlist[pn].new(0);
    cs[0]~children.new(0);
    cs[0]~targets.new(0);
    cs[0]~sounds.new(0);
  }];
}

public void nextRound()
{
  .resetGbl();
  .com.intro = .fight~ro.start_waittime + .fight~ro.ctrl_time+1;
  .com.time = .com.roundTime;
  .id = .cfg.HelperMax;
  if(.stg~resetbg) .stg~reset();
  .com.cam.update!.stg<>.self?(1.0, 0.0, 0.0, .stg<>=);
  loop{index i = 0; while; do:
    if(#.chars[i] == 0) continue;
    .chars[i][0]~[void(c=){
      .id = .m.max!int?(.id, c.id + 1);
      .charClear(i);
      c.posReset();
      c.setCtrl(false);
      c.stVal.clear();
      c.clearSpSysVar();
      c.rangeSetIVar(0, c.sysivar[.iINTPERSISTINDEX]-1, 0);
      c.rangeSetFVar(0, c.sysivar[.iFLOATPERSISTINDEX]-1, 0.0);
      loop{index j = 0; while; do:
        c.cmd[j].bufReset();
        j++;
      while j < #.chars:}
      if(.com.rexisted[c.playerno&1] == 0){
        .cgi[c.playerno].sf~palList.resetRemap();
        if(.cgi[c.playerno].sf~head.ver0 == 0d1){
          c.trRemapPal(1, 1, 1, .cgi[c.playerno].drawpalno);
        }
      }
      .cgi[c.playerno].clearPCTime();
      .cgi[c.playerno].unhittable = 0;
    }];
  continue:
    i++;
  while i < #.chars:}
  .chars:<-[void(c){if(#c > 0) c<>~trSelfState(5900, 0, 0);}];
}


public bool roundOver()
{
  if(
    .com.intro < -(
      .fight~ro.over_hittime
      + .fight~ro.over_waittime + .fight~ro.over_wintime)
    && .com.tickFrame() && .cmd.anybutton())
  {
    .com.intro =
      .m.min!int?(
        .com.intro,
        -(
          .fight~ro.over_hittime + .fight~ro.over_waittime
          + (.fight~ro.over_time - .fight~ro.start_waittime)));
    .winskipped = true;
  }
  ret
    .com.intro < -(
      .fight~ro.over_hittime + .fight~ro.over_waittime + .fight~ro.over_time);
}

